/*
 * Copyright (c) United Binary LLC.  All rights reserved.
 * 
 * This code is licensed under the MIT License
 * 
 * SEE: http://harnessit.codeplex.com/license
 * 
 */
#region using ...

using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using UnitedBinary.Core.Application.Configuration.CommandLine;
using UnitedBinary.Core.Windows.Forms;
using UnitedBinary.Core.Windows.Forms.Persistence;
using UnitedBinary.Core.Windows.Forms.Stock;
using UnitedBinary.Core.Windows.Forms.Utility;
using UnitedBinary.HarnessIt.Controls;
using UnitedBinary.HarnessIt.ExecutionCore;
using UnitedBinary.HarnessIt.SharedTypes;
using UnitedBinary.HarnessIt.TestEngine;
using UnitedBinary.UnitTests.Framework;
using UnitedBinary.UnitTests.Framework.TestItems;
using TabControl=Crownwood.Magic.Controls.TabControl;
using TabPage=Crownwood.Magic.Controls.TabPage;
using Timer=System.Windows.Forms.Timer;
using System.Collections.Generic;
using UnitedBinary.HarnessIt.Forms;

#endregion

namespace UnitedBinary.HarnessIt
{
	/// <summary>
	///		MainForm is the main form of the HarnessIt application.
	/// </summary>
	internal class MainForm : Form, IMethodLookup
	{
		private const string AnalyzingStatusText = "Analyzing test results, please wait...";
		#region Member Variables

		//public static SplashForm Splash = null;

		private MenuItem menuItem3;
		private MenuItem menuItem6;
		private MenuItem menuItemSaveProject;
		private MenuItem menuItemFile;
		private MenuItem menuItemNewProject;
		private MenuItem menuItemLoadProject;
		private MenuItem menuItemExit;
		private MenuItem menuItemTests;
		private MenuItem menuItemAddAsm;
		private MenuItem menuItemRunTests;
		private MenuItem menuItemView;
		private MenuItem menuItemHelp;
		private MenuItem menuItemAbout;
		private MainMenu mainMenu;
		private MenuItem menuItemView_ClassView;
		private MenuItem menuItemView_ProjectView;
		private MenuItem menuItem1;
		private MenuItem menuItemMainRemoveAssembly;
		private MenuItem menuItem2;
		private MenuItem menuItemSaveLog;
		private MenuItem menuItemGeneralHelp;
		private MenuItem menuItemUBOnline;
		private MenuItem menuItemTip;
		private MenuItem menuItem7;
		private MenuItem menuItem9;
		private MenuItem menuItemRecentProjects;
		private MenuItem menuItemEmptyPlaceHolder;
		private MenuItem menuItem12;
		private MenuItem menuItemSaveProjectAs;
		private MenuItem menuItemPurchase;
		private MenuItem menuItemCopySelected;
		private MenuItem menuItemSaveAsReport;
		private MenuItem menuItem5;
		private MenuItem menuItemCopyAll;
		private ContextMenu contextMenuReports;

		private StatusBar statusBarMain;
		private OpenFileDialog openFileDialogAssam;
		private OpenFileDialog openFileDialogProject;
		private SaveFileDialog saveFileDialogProject;
		private SaveFileDialog saveFileDialogLogs;

		private TabControl tabControlTreeViews;
		private TabPage tabPageClassView;
		private TabPage tabPageSolutionView;

		private TreeView treeViewClasses;
		private TreeView treeViewSolution;
		private ImageList imageListSolutionView;
		private ImageList imageListTreeTab;
		private ImageList imageListReportTabs;

		private IContainer components;
		private Panel panel1;
		private Splitter splitter1;
		private Panel panel2;
		private Font font8 = new Font( "Arial", 8 );

		private EngineEnumerator testEngineEnumerator = null;
		private ITestEngine iTestEngine = null;

		private List<Assembly> Assemblies = new List<Assembly>();
		private TimeSpan runningTime = new TimeSpan( 0 );
		private TestProject proj = new TestProject();

		private RecentFileManager recentFileManager;
		private bool oneTip = false;
		private MenuItem menuItem10;
		private MenuItem menuItemTestEngines;
		private string AppTitle;
		private MenuItem menuItemRegister;
		private MenuItem menuItemRegSeparator;
		private bool userCancelledTests = false;
		private bool autoClassViewContinue = false;
		private ContextMenu mnuProjectView;
		private ContextMenu mnuClassView;
		private MenuItem menuItemCVAddAssembly;
		private MenuItem menuItemPVAddAssembly;
		private MenuItem menuItemPVRemoveAssembly;

		//
		// Navigation forwards and backwards related variables.
		//
		private int historyCapacity = 15;
		private ArrayList history = new ArrayList();
		private int historyIndex = 0;

		private MenuItem menuItemView_Sep2;
		private MenuItem menuItemView_NavBack;
		private MenuItem menuItemView_NavForward;
		private Timer timerGUIUpdate;
		private TestResultsControl testResultsControl;

		private delegate void ProjectEvent();

		private event ProjectEvent ProjectClosing;
		private event ProjectEvent ProjectOpened;

		private HarnessItTraceListener harnessitListener;

		#endregion

		#region Construction, Deconstruction and Startup

		internal MainForm()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

			MainFormPersistentSplitterState ss = new MainFormPersistentSplitterState( splitter1 );
			ss.Initialize();

			this.AppTitle = this.Text;
			testResultsControl.Lookup = this;

			//
			// Add any constructor code after InitializeComponent call
			//
			ProjectClosing += OnProjectClosing;
			ProjectOpened += OnProjectOpened;

			SetupRichTextBoxes();
			SetupRecentFilesMenu();
			SetupMouseDownEvents( this );

			//
			// Remove all our cached local assembly files.  This may seem
			// out of place to delete them here.  But once they are loaded,
			// they are locked by HarnessIt so this is our only chance to 
			// clean them up.
			//
			CleanLocalTestAssemblyDir();

			SetupTestEngine();

			//
			// Seed our history; set to default startup tab selectedIndex.
			//
			history.Add( 0 );

			//
			// Start the GUI update timer.
			//
			timerGUIUpdate.Start();
		}

		private void SetupRichTextBoxes()
		{
			// TODO: Fix trace
			//harnessitListener = new HarnessItTraceListener( richTextBoxTrace );
			//Trace.Listeners.Add( harnessitListener );
			//harnessitListener.RichTextComp.TextRendered += TraceViewTextRendered;
		}

		private void SetupTestEngine()
		{
			try
			{
				testEngineEnumerator = new EngineEnumerator( EnginePath );
				testEngineEnumerator.Enumerate();

				iTestEngine = testEngineEnumerator.GetEngine( "UnitedBinary.HarnessIt.TestEngine.Local.LocalExecutionEngine" );
			}
			catch ( Exception e )
			{
				DetailedErrorForm.Show( "Error loading default test execution engine.", e.ToString() );
			}
		}

		private void SetupRecentFilesMenu()
		{
			recentFileManager = new RecentFileManager( menuItemRecentProjects, "United Binary\\HarnessIt" );
			recentFileManager.FileClick += new RecentFileManager.FileClickEventHandler( LoadRecentFile );
		}

		private void OnLoad(object sender, EventArgs e)
		{
			try
			{
				//
				// Initialize the window size / position using the persistent values.
				//
				MainFormPersistentState ps = new MainFormPersistentState( this );
				//Splash.Close();

                //if ( RegistrationTracker.RegistrationMode == RegistrationModes.Registered )
                //{
				Debug.WriteLine( "Registration Info: OSS Version - No Key Required." );
                //Debug.WriteLine( "Registration Info: " + RegistrationTracker.RegistrationInfo );
				menuItemRegister.Visible = false;
				menuItemRegSeparator.Visible = false;
                //}
                //else
                //{
                //    if ( !SystemInformation.UserInteractive )
                //    {
                //        EmergencyLog.WriteLine( "Licensing Error.", "Can not launch HarnessIt non-interactively unless registered." );
                //        this.Close();
                //    }
                //    else
                //    {
                //        // if running in unattended mode, STOP EXECUTING!
                //        Debug.WriteLine( "Registration Info: Executing in TRIAL mode." );
                //        NagForm nag = new NagForm();
                //        if (nag.TrialDaysRemaining < 15)
                //        {
                //            nag.Left = ps.Left + (ps.Width - nag.Width) / 2;
                //            nag.Top = ps.Top + (ps.Height - nag.Height) / 2;

                //            if ( nag.ShowDialog( this ) == DialogResult.Cancel )
                //            {
                //                this.Close();
                //                return;
                //            }
                //        }

                //        AppTitle = string.Format( "HarnessIt (Evaluation Version: {0} days)", nag.TrialDaysRemaining );
                //    }
				//}

				ps.InitializeWindow();

				ProcessCommandLine();
				ShowTips( true );
			}
			catch ( Exception ex )
			{
				MessageBox.Show( ex.ToString() );
			}
		}

		private void ProcessCommandLine()
		{
			CommandLineString cmdStr = new CommandLineString();
			cmdStr.CommandLine = Environment.CommandLine;
			Debug.WriteLine( "Commandline = " + Environment.CommandLine );

			proj = new TestProject();
			bool error = false;
			if ( cmdStr.ContainsValue( "proj" ) )
			{
				string file = "";
				try
				{
					SetShowTipOfTheDay( false );
					file = cmdStr.GetValue( "proj" );
					file = Path.GetFullPath( file );
					LoadProject( file );
				}
				catch ( ArgumentException e )
				{
					error = true;
					DetailedErrorForm.Show(
						"You must specify a project file when using the /proj command.\r\ne.g.\r\n\r\n\tHarnessIt.exe /proj=C:\\My Dir\\My Project.htp",
						e.ToString() );
				}
				catch ( Exception e )
				{
					bool handled = false;
					if ( e.InnerException != null )
					{
						if ( e.InnerException.GetType() == typeof (FileNotFoundException) )
						{
							error = true;
							handled = true;
							DetailedErrorForm.Show( "The project file \"" + file + "\" could not be found.", e.ToString() );
						}
						else if ( e.InnerException.GetType() == typeof (DirectoryNotFoundException) )
						{
							error = true;
							handled = true;
							DetailedErrorForm.Show( "The project directory could not be found.\r\n\r\n" + e.InnerException.Message,
							                        e.ToString() );
						}
					}

					if ( !handled )
					{
						error = true;
						DetailedErrorForm.Show(
							"An error has occurred when loading project \"" + Path.GetFullPath( file ) + "\".\r\n" + e.Message, e.ToString() );
					}
				}
			}
			else
			{
				ProjectOpened();
			}

			if ( error )
			{
				ProjectOpened();
				return;
			}

			bool testHaveRun = false;
			if ( cmdStr.ContainsValue( "run" ) )
			{
				string val = cmdStr.GetValue( "run" );
				val = val.ToLower();
				if ( val != null && val == "true" )
				{
					SetShowTipOfTheDay( false );
					testHaveRun = true;
					RunTests();
				}

				if ( !(val == "false" || val == "true") && val != null )
				{
					DetailedErrorForm.Show(
						"Command-line error: The only accepted values for run are 'true' and 'false'. e.g.\r\n\r\n\tHarnessIt.exe /proj=My Project.htp /run=true.\r\n\r\nYou specified the value '" +
						val + "'.", "No Details" );
				}
				else if ( val == null )
				{
					DetailedErrorForm.Show(
						"Command-line error: The only accepted values for run are 'true' and 'false'. e.g.\r\n\r\n\tHarnessIt.exe /proj=My Project.htp /run=true.\r\n\r\nYou specified the value 'null'.",
						"No Details" );
				}
			}

			bool saveSucceeded = false;
			if ( cmdStr.ContainsValue( "logfile" ) )
			{
				string logfile = cmdStr.GetValue( "logfile" );

				if ( logfile == null || logfile.Length == 0 )
				{
					DetailedErrorForm.Show(
						"Command-line error: You must specify a filename when using the logfile command. e.g.\r\n\r\n\tHarnessIt.exe /logfile=Log.rtf /proj=My Project.htp /run=true.",
						"No Details" );
					return;
				}

				try
				{
					if ( cmdStr.ContainsValue( "cyclelog" ) )
					{
						if ( cmdStr.GetValue( "cyclelog" ).ToLower() == "bydate" )
						{
							logfile = AddDateSuffixToFilename( logfile );
						}
					}

					ReportFormat format = ReportFormat.RTF;
					if ( cmdStr.ContainsValue( "logformat" ) )
					{
						string logformat = cmdStr.GetValue( "logformat" ).ToLower().Trim();
						if ( logformat == "rtf" )
						{
							format = ReportFormat.RTF;
						}
						else if ( logformat == "xml" )
						{
							format = ReportFormat.XML;
						}
						else
						{
							DetailedErrorForm.Show(
								"Command-line error: Unrecognized log file format. You must specify either RTF or XML. e.g.\r\n\r\n\tHarnessIt.exe /logfile=Log.xml /logformat=/XML /proj=My Project.htp /run=true.",
								"No Details" );
							return;
						}
					}
					SaveLog( logfile, format );
					saveSucceeded = true;
				}
				catch ( Exception e )
				{
					DetailedErrorForm.Show( "Error saving logfile \"" + logfile + "\".", e.ToString() );
					saveSucceeded = false;
				}
			}

			if ( cmdStr.ContainsValue( "close" ) && userCancelledTests == false )
			{
				string val = cmdStr.GetValue( "close" );
				val = val.ToLower();
				if ( val == "true" || val == "always" )
				{
					if ( cmdStr.ContainsValue( "logfile" ) && saveSucceeded && testHaveRun )
					{
						SetShowTipOfTheDay( false );
						this.Close();
					}
					else if ( !cmdStr.ContainsValue( "logfile" ) )
					{
						string err = "The log file was not specified. The \"close\" option " +
						             "does not make sense in this context and is consequently ignored.\r\n" +
						             "To specify a log file add /logfile=C:\\Path\\File.rtf to the command line.";
						DetailedErrorForm.Show( err, "No Details" );
					}
					else if ( !testHaveRun )
					{
						string err = "No tests have been run. The \"close\" option " +
						             "does not make sense in this context and is consequently ignored.\r\n" +
						             "To run the tests add /run=true to the command line arguments.";
						DetailedErrorForm.Show( err, "No Details" );
					}
				}
				else if ( val == "success" )
				{
					if ( TestsFailed == false )
					{
						SetShowTipOfTheDay( false );
						this.Close();
					}
				}
				else if ( val != "false" && val != "never" )
				{
					string err =
						"Command-line error: The accepted values for close are 'always', 'success', and 'never'. e.g.\r\n\r\n\tHarnessIt.exe /close=success /proj=My Project.htp /run=true.\r\n\r\nYou specified the value '" +
						val + "'.";
					DetailedErrorForm.Show( err, "No Details" );
				}
			}
		}

		private string AddDateSuffixToFilename(string filename)
		{
			string ext = "";
			if ( filename.IndexOf( "." ) >= 0 )
			{
				ext = Path.GetExtension( filename );
				if ( ext.Length > 0 )
				{
					filename = filename.Remove( filename.Length - ext.Length, ext.Length );
				}
			}

			StringBuilder dateStr = new StringBuilder();
			dateStr.Append( "." );
			dateStr.Append( DateTime.Now.Year );
			dateStr.Append( PadNumericString( DateTime.Now.Month ) );
			dateStr.Append( PadNumericString( DateTime.Now.Day ) );
			dateStr.Append( "-" );
			dateStr.Append( PadNumericString( DateTime.Now.Hour ) );
			dateStr.Append( PadNumericString( DateTime.Now.Minute ) );
			dateStr.Append( PadNumericString( DateTime.Now.Second ) );

			filename = filename + dateStr.ToString();
			if ( ext.Length > 0 )
			{
				filename += ext;
			}

			return filename;
		}

		private string PadNumericString(int number)
		{
			if ( number < 10 )
			{
				return "0" + number.ToString();
			}

			return number.ToString();
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose(bool disposing)
		{
			if ( disposing )
			{
				if ( components != null )
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

				#endregion

		#region Windows Form Designer generated code

		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
            this.components = new System.ComponentModel.Container();
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
            this.menuItemHelp = new System.Windows.Forms.MenuItem();
            this.menuItemGeneralHelp = new System.Windows.Forms.MenuItem();
            this.menuItem9 = new System.Windows.Forms.MenuItem();
            this.menuItemUBOnline = new System.Windows.Forms.MenuItem();
            this.menuItemPurchase = new System.Windows.Forms.MenuItem();
            this.menuItemRegSeparator = new System.Windows.Forms.MenuItem();
            this.menuItemRegister = new System.Windows.Forms.MenuItem();
            this.menuItem7 = new System.Windows.Forms.MenuItem();
            this.menuItemTip = new System.Windows.Forms.MenuItem();
            this.menuItemAbout = new System.Windows.Forms.MenuItem();
            this.treeViewClasses = new System.Windows.Forms.TreeView();
            this.mnuClassView = new System.Windows.Forms.ContextMenu();
            this.menuItemCVAddAssembly = new System.Windows.Forms.MenuItem();
            this.treeViewSolution = new System.Windows.Forms.TreeView();
            this.imageListSolutionView = new System.Windows.Forms.ImageList(this.components);
            this.mnuProjectView = new System.Windows.Forms.ContextMenu();
            this.menuItemPVAddAssembly = new System.Windows.Forms.MenuItem();
            this.menuItemPVRemoveAssembly = new System.Windows.Forms.MenuItem();
            this.imageListTreeTab = new System.Windows.Forms.ImageList(this.components);
            this.menuItemSaveProject = new System.Windows.Forms.MenuItem();
            this.contextMenuReports = new System.Windows.Forms.ContextMenu();
            this.menuItemCopySelected = new System.Windows.Forms.MenuItem();
            this.menuItemCopyAll = new System.Windows.Forms.MenuItem();
            this.menuItem5 = new System.Windows.Forms.MenuItem();
            this.menuItemSaveAsReport = new System.Windows.Forms.MenuItem();
            this.openFileDialogAssam = new System.Windows.Forms.OpenFileDialog();
            this.menuItemView_ProjectView = new System.Windows.Forms.MenuItem();
            this.saveFileDialogLogs = new System.Windows.Forms.SaveFileDialog();
            this.menuItemAddAsm = new System.Windows.Forms.MenuItem();
            this.menuItemView = new System.Windows.Forms.MenuItem();
            this.menuItemView_NavBack = new System.Windows.Forms.MenuItem();
            this.menuItemView_NavForward = new System.Windows.Forms.MenuItem();
            this.menuItemView_Sep2 = new System.Windows.Forms.MenuItem();
            this.menuItemView_ClassView = new System.Windows.Forms.MenuItem();
            this.menuItemExit = new System.Windows.Forms.MenuItem();
            this.menuItem3 = new System.Windows.Forms.MenuItem();
            this.saveFileDialogProject = new System.Windows.Forms.SaveFileDialog();
            this.mainMenu = new System.Windows.Forms.MainMenu(this.components);
            this.menuItemFile = new System.Windows.Forms.MenuItem();
            this.menuItemNewProject = new System.Windows.Forms.MenuItem();
            this.menuItemLoadProject = new System.Windows.Forms.MenuItem();
            this.menuItemSaveProjectAs = new System.Windows.Forms.MenuItem();
            this.menuItem2 = new System.Windows.Forms.MenuItem();
            this.menuItemSaveLog = new System.Windows.Forms.MenuItem();
            this.menuItem6 = new System.Windows.Forms.MenuItem();
            this.menuItemMainRemoveAssembly = new System.Windows.Forms.MenuItem();
            this.menuItem1 = new System.Windows.Forms.MenuItem();
            this.menuItemRecentProjects = new System.Windows.Forms.MenuItem();
            this.menuItemEmptyPlaceHolder = new System.Windows.Forms.MenuItem();
            this.menuItem12 = new System.Windows.Forms.MenuItem();
            this.menuItemTests = new System.Windows.Forms.MenuItem();
            this.menuItemRunTests = new System.Windows.Forms.MenuItem();
            this.menuItem10 = new System.Windows.Forms.MenuItem();
            this.menuItemTestEngines = new System.Windows.Forms.MenuItem();
            this.imageListReportTabs = new System.Windows.Forms.ImageList(this.components);
            this.openFileDialogProject = new System.Windows.Forms.OpenFileDialog();
            this.statusBarMain = new System.Windows.Forms.StatusBar();
            this.tabControlTreeViews = new Crownwood.Magic.Controls.TabControl();
            this.tabPageClassView = new Crownwood.Magic.Controls.TabPage();
            this.tabPageSolutionView = new Crownwood.Magic.Controls.TabPage();
            this.panel1 = new System.Windows.Forms.Panel();
            this.splitter1 = new System.Windows.Forms.Splitter();
            this.panel2 = new System.Windows.Forms.Panel();
            this.testResultsControl = new UnitedBinary.HarnessIt.Controls.TestResultsControl();
            this.timerGUIUpdate = new System.Windows.Forms.Timer(this.components);
            this.tabControlTreeViews.SuspendLayout();
            this.tabPageClassView.SuspendLayout();
            this.tabPageSolutionView.SuspendLayout();
            this.panel1.SuspendLayout();
            this.panel2.SuspendLayout();
            this.SuspendLayout();
            // 
            // menuItemHelp
            // 
            this.menuItemHelp.Index = 3;
            this.menuItemHelp.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.menuItemGeneralHelp,
            this.menuItem9,
            this.menuItemUBOnline,
            this.menuItemPurchase,
            this.menuItemRegSeparator,
            this.menuItemRegister,
            this.menuItem7,
            this.menuItemTip,
            this.menuItemAbout});
            this.menuItemHelp.Text = "&Help";
            // 
            // menuItemGeneralHelp
            // 
            this.menuItemGeneralHelp.Index = 0;
            this.menuItemGeneralHelp.Shortcut = System.Windows.Forms.Shortcut.F1;
            this.menuItemGeneralHelp.Text = "&General Help";
            this.menuItemGeneralHelp.Click += new System.EventHandler(this.OnClickGeneralHelp);
            // 
            // menuItem9
            // 
            this.menuItem9.Index = 1;
            this.menuItem9.Text = "-";
            // 
            // menuItemUBOnline
            // 
            this.menuItemUBOnline.Index = 2;
            this.menuItemUBOnline.Text = "&HarnessIt Online";
            this.menuItemUBOnline.Click += new System.EventHandler(this.OnClickUBOnline);
            // 
            // menuItemPurchase
            // 
            this.menuItemPurchase.Index = 3;
            this.menuItemPurchase.Text = "&Purchase";
            this.menuItemPurchase.Visible = false;
            this.menuItemPurchase.Click += new System.EventHandler(this.menuItemPurchase_Click);
            // 
            // menuItemRegSeparator
            // 
            this.menuItemRegSeparator.Index = 4;
            this.menuItemRegSeparator.Text = "-";
            // 
            // menuItemRegister
            // 
            this.menuItemRegister.Index = 5;
            this.menuItemRegister.Text = "&Register HarnessIt";
            this.menuItemRegister.Click += new System.EventHandler(this.menuItemRegister_Click);
            // 
            // menuItem7
            // 
            this.menuItem7.Index = 6;
            this.menuItem7.Text = "-";
            // 
            // menuItemTip
            // 
            this.menuItemTip.Index = 7;
            this.menuItemTip.Text = "&Tip of the Day";
            this.menuItemTip.Click += new System.EventHandler(this.OnClickShowTip);
            // 
            // menuItemAbout
            // 
            this.menuItemAbout.Index = 8;
            this.menuItemAbout.Text = "&About HarnessIt";
            this.menuItemAbout.Click += new System.EventHandler(this.OnHelpAbout);
            // 
            // treeViewClasses
            // 
            this.treeViewClasses.BorderStyle = System.Windows.Forms.BorderStyle.None;
            this.treeViewClasses.CheckBoxes = true;
            this.treeViewClasses.ContextMenu = this.mnuClassView;
            this.treeViewClasses.Dock = System.Windows.Forms.DockStyle.Fill;
            this.treeViewClasses.HideSelection = false;
            this.treeViewClasses.Location = new System.Drawing.Point(0, 0);
            this.treeViewClasses.Name = "treeViewClasses";
            this.treeViewClasses.ShowRootLines = false;
            this.treeViewClasses.Size = new System.Drawing.Size(198, 363);
            this.treeViewClasses.Sorted = true;
            this.treeViewClasses.TabIndex = 0;
            this.treeViewClasses.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.OnCheck);
            this.treeViewClasses.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.OnAfterSelectClassView);
            // 
            // mnuClassView
            // 
            this.mnuClassView.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.menuItemCVAddAssembly});
            // 
            // menuItemCVAddAssembly
            // 
            this.menuItemCVAddAssembly.Index = 0;
            this.menuItemCVAddAssembly.Text = "Add Assembly";
            this.menuItemCVAddAssembly.Click += new System.EventHandler(this.OnAddAssembly);
            // 
            // treeViewSolution
            // 
            this.treeViewSolution.BorderStyle = System.Windows.Forms.BorderStyle.None;
            this.treeViewSolution.Dock = System.Windows.Forms.DockStyle.Fill;
            this.treeViewSolution.HideSelection = false;
            this.treeViewSolution.ImageIndex = 0;
            this.treeViewSolution.ImageList = this.imageListSolutionView;
            this.treeViewSolution.Location = new System.Drawing.Point(0, 0);
            this.treeViewSolution.Name = "treeViewSolution";
            this.treeViewSolution.SelectedImageIndex = 0;
            this.treeViewSolution.ShowPlusMinus = false;
            this.treeViewSolution.ShowRootLines = false;
            this.treeViewSolution.Size = new System.Drawing.Size(198, 363);
            this.treeViewSolution.Sorted = true;
            this.treeViewSolution.TabIndex = 2;
            this.treeViewSolution.KeyDown += new System.Windows.Forms.KeyEventHandler(this.OnKeyDownSolView);
            this.treeViewSolution.MouseUp += new System.Windows.Forms.MouseEventHandler(this.OnProjectViewMouseUp);
            // 
            // imageListSolutionView
            // 
            this.imageListSolutionView.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageListSolutionView.ImageStream")));
            this.imageListSolutionView.TransparentColor = System.Drawing.Color.Cyan;
            this.imageListSolutionView.Images.SetKeyName(0, "");
            this.imageListSolutionView.Images.SetKeyName(1, "");
            // 
            // mnuProjectView
            // 
            this.mnuProjectView.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.menuItemPVAddAssembly,
            this.menuItemPVRemoveAssembly});
            // 
            // menuItemPVAddAssembly
            // 
            this.menuItemPVAddAssembly.Index = 0;
            this.menuItemPVAddAssembly.Text = "Add Assembly";
            this.menuItemPVAddAssembly.Click += new System.EventHandler(this.OnAddAssembly);
            // 
            // menuItemPVRemoveAssembly
            // 
            this.menuItemPVRemoveAssembly.Index = 1;
            this.menuItemPVRemoveAssembly.Text = "Remove Assembly";
            this.menuItemPVRemoveAssembly.Click += new System.EventHandler(this.OnRemoveAssembly);
            // 
            // imageListTreeTab
            // 
            this.imageListTreeTab.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageListTreeTab.ImageStream")));
            this.imageListTreeTab.TransparentColor = System.Drawing.Color.Cyan;
            this.imageListTreeTab.Images.SetKeyName(0, "");
            this.imageListTreeTab.Images.SetKeyName(1, "");
            this.imageListTreeTab.Images.SetKeyName(2, "");
            // 
            // menuItemSaveProject
            // 
            this.menuItemSaveProject.Index = 3;
            this.menuItemSaveProject.Shortcut = System.Windows.Forms.Shortcut.CtrlS;
            this.menuItemSaveProject.Text = "&Save Project";
            this.menuItemSaveProject.Click += new System.EventHandler(this.OnSaveProject);
            // 
            // contextMenuReports
            // 
            this.contextMenuReports.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.menuItemCopySelected,
            this.menuItemCopyAll,
            this.menuItem5,
            this.menuItemSaveAsReport});
            this.contextMenuReports.Popup += new System.EventHandler(this.contextMenuReports_Popup);
            // 
            // menuItemCopySelected
            // 
            this.menuItemCopySelected.Index = 0;
            this.menuItemCopySelected.Shortcut = System.Windows.Forms.Shortcut.CtrlC;
            this.menuItemCopySelected.Text = "&Copy";
            this.menuItemCopySelected.Click += new System.EventHandler(this.menuItemCopySelected_Click);
            // 
            // menuItemCopyAll
            // 
            this.menuItemCopyAll.Index = 1;
            this.menuItemCopyAll.Text = "Copy &All";
            this.menuItemCopyAll.Click += new System.EventHandler(this.menuItemCopyAll_Click);
            // 
            // menuItem5
            // 
            this.menuItem5.Index = 2;
            this.menuItem5.Text = "-";
            // 
            // menuItemSaveAsReport
            // 
            this.menuItemSaveAsReport.Index = 3;
            this.menuItemSaveAsReport.Text = "&Save As Report";
            this.menuItemSaveAsReport.Click += new System.EventHandler(this.menuItemSaveAsReport_Click);
            // 
            // openFileDialogAssam
            // 
            this.openFileDialogAssam.DefaultExt = "dll";
            this.openFileDialogAssam.Filter = "All Assemblies (*.dll, *.exe)|*.dll;*.exe|Class Libraries (*.dll)|*.dll|Executabl" +
                "es (*.exe)|*.exe|All files|*.*";
            this.openFileDialogAssam.ShowReadOnly = true;
            this.openFileDialogAssam.Title = "Load Assembly";
            // 
            // menuItemView_ProjectView
            // 
            this.menuItemView_ProjectView.Index = 4;
            this.menuItemView_ProjectView.Shortcut = System.Windows.Forms.Shortcut.CtrlP;
            this.menuItemView_ProjectView.Text = "&Project View";
            this.menuItemView_ProjectView.Click += new System.EventHandler(this.OnShowProjectView);
            // 
            // saveFileDialogLogs
            // 
            this.saveFileDialogLogs.AddExtension = false;
            this.saveFileDialogLogs.FileName = "HarnessIt Report";
            this.saveFileDialogLogs.Filter = "Rich Text Documents (*.rtf)|*.rtf|Xml Documents (*.xml)|*.xml";
            this.saveFileDialogLogs.FilterIndex = 2;
            this.saveFileDialogLogs.Title = "Save Test Report";
            // 
            // menuItemAddAsm
            // 
            this.menuItemAddAsm.Index = 8;
            this.menuItemAddAsm.Shortcut = System.Windows.Forms.Shortcut.CtrlA;
            this.menuItemAddAsm.Text = "A&dd Assembly ...";
            this.menuItemAddAsm.Click += new System.EventHandler(this.OnAddAssembly);
            // 
            // menuItemView
            // 
            this.menuItemView.Index = 2;
            this.menuItemView.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.menuItemView_NavBack,
            this.menuItemView_NavForward,
            this.menuItemView_Sep2,
            this.menuItemView_ClassView,
            this.menuItemView_ProjectView});
            this.menuItemView.Text = "&View";
            // 
            // menuItemView_NavBack
            // 
            this.menuItemView_NavBack.Index = 0;
            this.menuItemView_NavBack.Shortcut = System.Windows.Forms.Shortcut.CtrlB;
            this.menuItemView_NavBack.Text = "Navigate &Backward";
            this.menuItemView_NavBack.Click += new System.EventHandler(this.menuItemView_NavBack_Click);
            // 
            // menuItemView_NavForward
            // 
            this.menuItemView_NavForward.Index = 1;
            this.menuItemView_NavForward.Shortcut = System.Windows.Forms.Shortcut.CtrlShiftB;
            this.menuItemView_NavForward.Text = "&Navigate Forward";
            this.menuItemView_NavForward.Click += new System.EventHandler(this.menuItemView_NavForward_Click);
            // 
            // menuItemView_Sep2
            // 
            this.menuItemView_Sep2.Index = 2;
            this.menuItemView_Sep2.Text = "-";
            // 
            // menuItemView_ClassView
            // 
            this.menuItemView_ClassView.Index = 3;
            this.menuItemView_ClassView.Shortcut = System.Windows.Forms.Shortcut.CtrlC;
            this.menuItemView_ClassView.Text = "&Class View";
            this.menuItemView_ClassView.Click += new System.EventHandler(this.OnShowClassView);
            // 
            // menuItemExit
            // 
            this.menuItemExit.Index = 13;
            this.menuItemExit.Shortcut = System.Windows.Forms.Shortcut.CtrlX;
            this.menuItemExit.Text = "E&xit";
            this.menuItemExit.Click += new System.EventHandler(this.OnExit);
            // 
            // menuItem3
            // 
            this.menuItem3.Index = 1;
            this.menuItem3.Text = "-";
            // 
            // saveFileDialogProject
            // 
            this.saveFileDialogProject.DefaultExt = "htp";
            this.saveFileDialogProject.FileName = "New Project.htp";
            this.saveFileDialogProject.Filter = "HarnessIt Projects (*.htp)|*.htp|All files|*.*";
            this.saveFileDialogProject.Title = "Save HarnessIt Project";
            // 
            // mainMenu
            // 
            this.mainMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.menuItemFile,
            this.menuItemTests,
            this.menuItemView,
            this.menuItemHelp});
            // 
            // menuItemFile
            // 
            this.menuItemFile.Index = 0;
            this.menuItemFile.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.menuItemNewProject,
            this.menuItem3,
            this.menuItemLoadProject,
            this.menuItemSaveProject,
            this.menuItemSaveProjectAs,
            this.menuItem2,
            this.menuItemSaveLog,
            this.menuItem6,
            this.menuItemAddAsm,
            this.menuItemMainRemoveAssembly,
            this.menuItem1,
            this.menuItemRecentProjects,
            this.menuItem12,
            this.menuItemExit});
            this.menuItemFile.Text = "&File";
            // 
            // menuItemNewProject
            // 
            this.menuItemNewProject.Index = 0;
            this.menuItemNewProject.Shortcut = System.Windows.Forms.Shortcut.CtrlN;
            this.menuItemNewProject.Text = "&New Project";
            this.menuItemNewProject.Click += new System.EventHandler(this.OnNewProject);
            // 
            // menuItemLoadProject
            // 
            this.menuItemLoadProject.Index = 2;
            this.menuItemLoadProject.Shortcut = System.Windows.Forms.Shortcut.CtrlL;
            this.menuItemLoadProject.Text = "&Load Project ...";
            this.menuItemLoadProject.Click += new System.EventHandler(this.OnLoadProject);
            // 
            // menuItemSaveProjectAs
            // 
            this.menuItemSaveProjectAs.Index = 4;
            this.menuItemSaveProjectAs.Text = "Save Project &As ...";
            this.menuItemSaveProjectAs.Click += new System.EventHandler(this.menuItemSaveProjectAs_Click);
            // 
            // menuItem2
            // 
            this.menuItem2.Index = 5;
            this.menuItem2.Text = "-";
            // 
            // menuItemSaveLog
            // 
            this.menuItemSaveLog.Index = 6;
            this.menuItemSaveLog.Text = "Save Test &Report ...";
            this.menuItemSaveLog.Click += new System.EventHandler(this.OnSaveLog);
            // 
            // menuItem6
            // 
            this.menuItem6.Index = 7;
            this.menuItem6.Text = "-";
            // 
            // menuItemMainRemoveAssembly
            // 
            this.menuItemMainRemoveAssembly.Index = 9;
            this.menuItemMainRemoveAssembly.Text = "Re&move Assembly";
            this.menuItemMainRemoveAssembly.Click += new System.EventHandler(this.OnRemoveAssembly);
            // 
            // menuItem1
            // 
            this.menuItem1.Index = 10;
            this.menuItem1.Text = "-";
            // 
            // menuItemRecentProjects
            // 
            this.menuItemRecentProjects.Index = 11;
            this.menuItemRecentProjects.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.menuItemEmptyPlaceHolder});
            this.menuItemRecentProjects.Text = "Recent &Projects";
            // 
            // menuItemEmptyPlaceHolder
            // 
            this.menuItemEmptyPlaceHolder.Enabled = false;
            this.menuItemEmptyPlaceHolder.Index = 0;
            this.menuItemEmptyPlaceHolder.Text = "(Empty)";
            // 
            // menuItem12
            // 
            this.menuItem12.Index = 12;
            this.menuItem12.Text = "-";
            // 
            // menuItemTests
            // 
            this.menuItemTests.Index = 1;
            this.menuItemTests.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.menuItemRunTests,
            this.menuItem10,
            this.menuItemTestEngines});
            this.menuItemTests.Text = "&Tests";
            // 
            // menuItemRunTests
            // 
            this.menuItemRunTests.Index = 0;
            this.menuItemRunTests.Shortcut = System.Windows.Forms.Shortcut.F5;
            this.menuItemRunTests.Text = "&Run";
            this.menuItemRunTests.Click += new System.EventHandler(this.OnRunTests);
            // 
            // menuItem10
            // 
            this.menuItem10.Index = 1;
            this.menuItem10.Text = "-";
            // 
            // menuItemTestEngines
            // 
            this.menuItemTestEngines.Index = 2;
            this.menuItemTestEngines.Shortcut = System.Windows.Forms.Shortcut.CtrlE;
            this.menuItemTestEngines.Text = "&Test Engines ...";
            this.menuItemTestEngines.Click += new System.EventHandler(this.menuItemTestEngines_Click);
            // 
            // imageListReportTabs
            // 
            this.imageListReportTabs.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageListReportTabs.ImageStream")));
            this.imageListReportTabs.TransparentColor = System.Drawing.Color.Cyan;
            this.imageListReportTabs.Images.SetKeyName(0, "");
            this.imageListReportTabs.Images.SetKeyName(1, "");
            this.imageListReportTabs.Images.SetKeyName(2, "");
            this.imageListReportTabs.Images.SetKeyName(3, "");
            this.imageListReportTabs.Images.SetKeyName(4, "");
            // 
            // openFileDialogProject
            // 
            this.openFileDialogProject.DefaultExt = "htp";
            this.openFileDialogProject.Filter = "HarnessIt Projects (*.htp)|*.htp|All files|*.*";
            this.openFileDialogProject.ShowReadOnly = true;
            this.openFileDialogProject.Title = "Open HarnessIt Project";
            // 
            // statusBarMain
            // 
            this.statusBarMain.Location = new System.Drawing.Point(0, 390);
            this.statusBarMain.Name = "statusBarMain";
            this.statusBarMain.Size = new System.Drawing.Size(708, 20);
            this.statusBarMain.TabIndex = 2;
            // 
            // tabControlTreeViews
            // 
            this.tabControlTreeViews.Dock = System.Windows.Forms.DockStyle.Fill;
            this.tabControlTreeViews.Font = new System.Drawing.Font("Tahoma", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.World);
            this.tabControlTreeViews.HotTrack = true;
            this.tabControlTreeViews.IDEPixelArea = true;
            this.tabControlTreeViews.Location = new System.Drawing.Point(0, 0);
            this.tabControlTreeViews.Name = "tabControlTreeViews";
            this.tabControlTreeViews.PositionTop = true;
            this.tabControlTreeViews.SelectedIndex = 0;
            this.tabControlTreeViews.SelectedTab = this.tabPageClassView;
            this.tabControlTreeViews.Size = new System.Drawing.Size(200, 390);
            this.tabControlTreeViews.TabIndex = 0;
            this.tabControlTreeViews.TabPages.AddRange(new Crownwood.Magic.Controls.TabPage[] {
            this.tabPageClassView,
            this.tabPageSolutionView});
            // 
            // tabPageClassView
            // 
            this.tabPageClassView.BackColor = System.Drawing.Color.White;
            this.tabPageClassView.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.tabPageClassView.Controls.Add(this.treeViewClasses);
            this.tabPageClassView.Cursor = System.Windows.Forms.Cursors.Hand;
            this.tabPageClassView.ImageIndex = 0;
            this.tabPageClassView.ImageList = this.imageListTreeTab;
            this.tabPageClassView.Location = new System.Drawing.Point(0, 25);
            this.tabPageClassView.Name = "tabPageClassView";
            this.tabPageClassView.Size = new System.Drawing.Size(200, 365);
            this.tabPageClassView.TabIndex = 3;
            this.tabPageClassView.Title = "Class View";
            // 
            // tabPageSolutionView
            // 
            this.tabPageSolutionView.BackColor = System.Drawing.Color.White;
            this.tabPageSolutionView.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.tabPageSolutionView.Controls.Add(this.treeViewSolution);
            this.tabPageSolutionView.ImageIndex = 1;
            this.tabPageSolutionView.ImageList = this.imageListTreeTab;
            this.tabPageSolutionView.Location = new System.Drawing.Point(0, 25);
            this.tabPageSolutionView.Name = "tabPageSolutionView";
            this.tabPageSolutionView.Selected = false;
            this.tabPageSolutionView.Size = new System.Drawing.Size(200, 365);
            this.tabPageSolutionView.TabIndex = 4;
            this.tabPageSolutionView.Title = "Project View";
            // 
            // panel1
            // 
            this.panel1.Controls.Add(this.tabControlTreeViews);
            this.panel1.Dock = System.Windows.Forms.DockStyle.Left;
            this.panel1.Location = new System.Drawing.Point(0, 0);
            this.panel1.Name = "panel1";
            this.panel1.Size = new System.Drawing.Size(200, 390);
            this.panel1.TabIndex = 3;
            // 
            // splitter1
            // 
            this.splitter1.Location = new System.Drawing.Point(200, 0);
            this.splitter1.MinSize = 100;
            this.splitter1.Name = "splitter1";
            this.splitter1.Size = new System.Drawing.Size(5, 390);
            this.splitter1.TabIndex = 4;
            this.splitter1.TabStop = false;
            // 
            // panel2
            // 
            this.panel2.Controls.Add(this.testResultsControl);
            this.panel2.Dock = System.Windows.Forms.DockStyle.Fill;
            this.panel2.Location = new System.Drawing.Point(205, 0);
            this.panel2.Name = "panel2";
            this.panel2.Size = new System.Drawing.Size(503, 390);
            this.panel2.TabIndex = 5;
            // 
            // testResultsControl
            // 
            this.testResultsControl.Dock = System.Windows.Forms.DockStyle.Fill;
            this.testResultsControl.Location = new System.Drawing.Point(0, 0);
            this.testResultsControl.Lookup = null;
            this.testResultsControl.Name = "testResultsControl";
            this.testResultsControl.Size = new System.Drawing.Size(503, 390);
            this.testResultsControl.TabIndex = 2;
            // 
            // timerGUIUpdate
            // 
            this.timerGUIUpdate.Interval = 1000;
            this.timerGUIUpdate.Tick += new System.EventHandler(this.timerGUIUpdate_Tick);
            // 
            // MainForm
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(708, 410);
            this.Controls.Add(this.panel2);
            this.Controls.Add(this.splitter1);
            this.Controls.Add(this.panel1);
            this.Controls.Add(this.statusBarMain);
            this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
            this.Menu = this.mainMenu;
            this.MinimumSize = new System.Drawing.Size(700, 300);
            this.Name = "MainForm";
            this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
            this.StartPosition = System.Windows.Forms.FormStartPosition.WindowsDefaultBounds;
            this.Text = "HarnessIt  (2.0 Beta 1)";
            this.Closing += new System.ComponentModel.CancelEventHandler(this.OnClosing);
            this.Load += new System.EventHandler(this.OnLoad);
            this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.AllControls_MouseDown);
            this.tabControlTreeViews.ResumeLayout(false);
            this.tabPageClassView.ResumeLayout(false);
            this.tabPageSolutionView.ResumeLayout(false);
            this.panel1.ResumeLayout(false);
            this.panel2.ResumeLayout(false);
            this.ResumeLayout(false);

		}

		#endregion

		#region Custom Event Handlers

		private void OnProjectClosing()
		{
			try
			{
				ClearTestReportingControls();

				SyncConfigFromProject( proj.Config );
				proj.SaveConfig();

				if ( proj.FullPathName.Length > 0 )
				{
					recentFileManager.Add( proj.FullPathName );
				}
			}
			catch ( Exception e )
			{
				Debug.WriteLine( "Error saving config: " + e.Message );
			}
		}

		private void OnProjectOpened()
		{
			CatchFalseChecking = true;
			SyncFormToProject( proj );
			if ( proj.ConfigOk )
			{
				SyncClassTreeEnabledStatesFromConfig( treeViewClasses.Nodes[0], proj.Config );
			}

			if ( proj.FullPathName.Length > 0 )
			{
				recentFileManager.Add( proj.FullPathName );
			}
			CatchFalseChecking = false;
		}

		private void LoadRecentFile(string file)
		{
			Debug.WriteLine( "Load recent file: " + file );

			if ( !CheckCloseProject() )
				return;

			LoadProject( file );
		}

		#endregion

		#region Menu and button event handling code

		[MethodImpl(MethodImplOptions.Synchronized)]
		private void timerGUIUpdate_Tick(object sender, EventArgs e)
		{
			string titleText;
			if ( proj.Changed )
			{
				titleText = AppTitle + " - [" + proj.Name + "*]";
			}
			else
			{
				titleText = AppTitle + " - [" + proj.Name + "]";
			}

			if ( this.Text != titleText )
			{
				this.Text = titleText;
			}
		}

		//private void richTextBoxOutput_LinkClicked(object sender, LinkClickedEventArgs e)
		//{
		//	string url = e.LinkText.Replace( '+', ' ' );

		//	if ( url.ToLower().StartsWith( "http://exceptionexplorer/" ) )
		//	{
		//		int start = "http://exceptionexplorer/".Length;
		//		string path = url.Substring( start );

		//		Cursor currentCursor = this.Cursor;
		//		try
		//		{
		//			this.Cursor = Cursors.WaitCursor;

		//			int index = path.ToLower().LastIndexOf( "?id=" );
		//			int idlength = "?id=".Length;
		//			int length = path.Length - idlength - index;
		//			string id = path.Substring( index + idlength, length );
		//			path = path.Substring( 0, index );

		//			int exceptionIndex = int.Parse( id ) - 1;

		//			Method m = LookUpMethod( path );

		//			//if ( m.TestRecord.TestExceptions.Length == 0 )
		//			//{
		//			//    StringBuilder sb = new StringBuilder();
		//			//    sb.Append( "No detailed information is available about this exception.\n" );
		//			//    sb.Append( "\n" );
		//			//    sb.Append( "This most often occurs when using non-default test engines.\n" );
		//			//    sb.Append( "We are currently upgrading the non-default test engines so they\n" );
		//			//    sb.Append( "can return detailed exception information." );

		//			//    if ( SystemInformation.UserInteractive )
		//			//    {
		//			//        MessageBox.Show( sb.ToString(), "HarnessIt", MessageBoxButtons.OK, MessageBoxIcon.Information );
		//			//    }
		//			//    else
		//			//    {
		//			//        EmergencyLog.WriteLine( "Exception error.", sb.ToString() );
		//			//    }

		//			//    return;
		//			//}

		//			TestException TE = m.TestRecord.TestExceptions[exceptionIndex];
		//			if ( TE.Message.IndexOf( "thrown by the target of an invocation" ) >= 0 )
		//			{
		//				TE = TE.InnerException;
		//			}

		//			ExceptionExplorerForm form = new ExceptionExplorerForm();
		//			form.LoadException( TE, path );
		//		}
		//		catch ( Exception ex )
		//		{
		//			if ( SystemInformation.UserInteractive )
		//			{
		//				MessageBox.Show( ex.Message, "HarnessIt Error", MessageBoxButtons.OK, MessageBoxIcon.Error );
		//			}
		//			else
		//			{
		//				EmergencyLog.WriteLine( "Exception occurred.", ex.Message );
		//			}
		//		}
		//		finally
		//		{
		//			this.Cursor = currentCursor;
		//		}
		//	}
		//	else
		//	{
		//		WebHelper web = new WebHelper();
		//		web.Navigate( e.LinkText );
		//	}
		//}

		//private void richTextBoxFailures_LinkClicked(object sender, LinkClickedEventArgs e)
		//{
		//	richTextBoxOutput_LinkClicked( sender, e );
		//}

		//private void richTextBoxReportExplorer_LinkClicked(object sender, LinkClickedEventArgs e)
		//{
		//	richTextBoxOutput_LinkClicked( sender, e );
		//}

		//private void richTextBoxTrace_LinkClicked(object sender, LinkClickedEventArgs e)
		//{
		//	richTextBoxOutput_LinkClicked( sender, e );
		//}

		public Method LookUpMethod(string methodPath)
		{
			string[] parts = methodPath.Split( new char[] {'/'} );
			if ( parts.Length != 3 )
			{
				throw new Exception( "Unrecognized format for Exception Explorer URL, navigation cancelled." );
			}

			string assemblyName = parts[0];
			string className = parts[1];
			string methodName = parts[2];

			foreach ( Assembly A in Assemblies )
			{
				if (A.Name != assemblyName)
				{
					continue;
				}

				Class[] classes = A.Classes;
				foreach (Class c in classes)
				{
					if (c.Name != className)
					{
						continue;
					}

					Method[] methods = c.Methods;
					foreach (Method m in methods)
					{
						if (m.Name == methodName)
						{
							return m;
						}
					}
				}
			}

			throw new Exception( "The method specified by the path " + methodPath + " could not be located." );
		}

		private void menuItemTestEngines_Click(object sender, EventArgs e)
		{
			// TODO: Add error checking here.
			// SHOW DIALOG AUDIT: This can ONLY happen when interactive -- no need to test UserInteractive here...
			TestEngineSelectionForm frm = new TestEngineSelectionForm( testEngineEnumerator, iTestEngine );
			if ( frm.ShowDialog() == DialogResult.OK )
			{
				iTestEngine = frm.SelectedEngine;
				SyncProjectToForm( this.proj );
			}
		}

		private void menuItemCopySelected_Click(object sender, EventArgs e)
		{
			// TODO: Fix when highlighting tests results.
			//if ( tabControlReports.SelectedTab == tabPageOutput )
			//{
			//	richTextBoxOutput.Copy();
			//}
			//else if ( tabControlReports.SelectedTab == tabPageReportExplorer )
			//{
			//	richTextBoxReportExplorer.Copy();
			//}
			//else if ( tabControlReports.SelectedTab == tabPageFailures )
			//{
			//	richTextBoxFailures.Copy();
			//}
			//else if ( tabControlReports.SelectedTab == tabPageTrace )
			//{
			//	richTextBoxTrace.Copy();
			//}
			//else
			{
				Debug.WriteLine( "Error: Unknown tab page in reports context menu." );
			}
		}

		private void menuItemSaveAsReport_Click(object sender, EventArgs e)
		{
			OnSaveLog( sender, e );
		}

		private void contextMenuReports_Popup(object sender, EventArgs e)
		{
			// TODO: Fix for new UI.

			//
			// Set the enabled state for the "Copy" menu item based on the state.
			//
			//bool selected = false;
			//bool copyAll = false;
			//if ( tabControlReports.SelectedTab == tabPageOutput )
			//{
			//	selected = richTextBoxOutput.SelectedText.Length > 0;
			//	copyAll = richTextBoxOutput.Text.Length > 0;
			//}
			//else if ( tabControlReports.SelectedTab == tabPageReportExplorer )
			//{
			//	if ( richTextBoxReportExplorer.SelectedText.Length > 0 )
			//	{
			//		selected = true;
			//	}
			//	copyAll = richTextBoxReportExplorer.Text.Length > 0;
			//}
			//else if ( tabControlReports.SelectedTab == tabPageFailures )
			//{
			//	if ( richTextBoxFailures.SelectedText.Length > 0 )
			//	{
			//		selected = true;
			//	}
			//	copyAll = richTextBoxFailures.Text.Length > 0;
			//}
			//else if ( tabControlReports.SelectedTab == tabPageTrace )
			//{
			//	if ( richTextBoxTrace.SelectedText.Length > 0 )
			//	{
			//		selected = true;
			//	}
			//	copyAll = richTextBoxTrace.Text.Length > 0;
			//}
			//else
			//{
			//	Debug.WriteLine( "Error: Unknown tab page in reports context menu." );
			//}
		//	menuItemCopySelected.Enabled = selected;

			//
			// Set the enabled state for the "Save As Report" menu item based on the state.
			//
			//selected = false;
			//foreach ( Assembly A in Assemblies )
			//{
			//	if ( A.TestRecord.HasRun )
			//	{
			//		selected = true;
			//		break;
			//	}
			//}
			//menuItemSaveAsReport.Enabled = selected;
		}

		private void menuItemCopyAll_Click(object sender, EventArgs e)
		{
			//if ( tabControlReports.SelectedTab == tabPageOutput )
			//{
			//	richTextBoxOutput.SelectAll();
			//	richTextBoxOutput.Copy();
			//	richTextBoxOutput.Select( 0, 0 );
			//}
			//else if ( tabControlReports.SelectedTab == tabPageReportExplorer )
			//{
			//	richTextBoxReportExplorer.SelectAll();
			//	richTextBoxReportExplorer.Copy();
			//	richTextBoxReportExplorer.Select( 0, 0 );
			//}
			//else if ( tabControlReports.SelectedTab == tabPageFailures )
			//{
			//	richTextBoxFailures.SelectAll();
			//	richTextBoxFailures.Copy();
			//	richTextBoxFailures.Select( 0, 0 );
			//}
			//else if ( tabControlReports.SelectedTab == tabPageTrace )
			//{
			//	richTextBoxTrace.SelectAll();
			//	richTextBoxTrace.Copy();
			//	richTextBoxTrace.Select( 0, 0 );
			//}
			//else
			//{
			//	Debug.WriteLine( "Error: Unknown tab page in reports context menu." );
			//}
		}

		private void menuItemPurchase_Click(object sender, EventArgs e)
		{
			//WebHelper web = new WebHelper();
			//web.Navigate( CustomSettings.PurchasingURL );
		}

		private void menuItemRegister_Click(object sender, EventArgs e)
		{
            //if ( RegistrationTracker.RegistrationMode == RegistrationModes.Registered )
            //{
            //    DetailedErrorForm.Show( "HarnessIt is already registered.", "No Details" );
            //    return;
            //}

            //RegisterHarnessIt();
		}

        //private void RegisterHarnessIt()
        //{
        //    // must be interactive...
        //    RegInfoForm frm = new RegInfoForm();
        //    if ( frm.ShowDialog() == DialogResult.OK )
        //    {
        //        MessageBox.Show( "HarnessIt will operate in evaluation mode until it has been restarted.",
        //                         "HarnessIt", MessageBoxButtons.OK, MessageBoxIcon.Warning );
        //    }
        //}

		/// <summary>
		///		Shows the TipOfTheDay form.
		/// </summary>
		/// <param name="checkShowAtStart">
		///		Indicates whether to check if the user wants Tips at startup and 
		///		if they have been shown this instance.
		///		</param>
		private void ShowTips(bool checkShowAtStart)
		{
			try
			{
				TipOfTheDayForm frm = new TipOfTheDayForm( "United Binary\\HarnessIt" );
				bool show = ((!oneTip && frm.LoadAtStart) || !checkShowAtStart) && SystemInformation.UserInteractive;
				oneTip = true;
				if ( show )
				{
					string file = AppDomain.CurrentDomain.BaseDirectory + @"Resources\HarnessIt.tip";
					frm.LoadTips( file );
					frm.ShowDialog();
				}
			}
			catch ( Exception e )
			{
				Debug.WriteLine( "Error showing Tip of the Day: " + e.Message );
			}
		}

		private void OnClickShowTip(object sender, EventArgs e)
		{
			ShowTips( false );
		}

		private void SetShowTipOfTheDay(bool state)
		{
			oneTip = !state;
		}

		private void OnClickUBOnline(object sender, EventArgs e)
		{
			WebHelper web = new WebHelper();
			web.Navigate( "http://harnessit.codeplex.com" );
		}

		private void OnClickGeneralHelp(object sender, EventArgs e)
		{
			try
			{
				string dir = AppDomain.CurrentDomain.BaseDirectory;
				Process.Start( dir + "Documentation\\HarnessIt.chm" );
			}
			catch ( Exception ex )
			{
				MessageBox.Show( "Error loading help:\n\n" + ex.Message, "HarnessIt Error", MessageBoxButtons.OK,
				                 MessageBoxIcon.Error );
			}
		}

		private void OnClosing(object sender, CancelEventArgs e)
		{
			if ( !CheckCloseProject() )
			{
				e.Cancel = true;
				return;
			}

			MainFormPersistentState ps = new MainFormPersistentState( this );
			ps.SaveWindow();

			MainFormPersistentSplitterState ss = new MainFormPersistentSplitterState( splitter1 );
			ss.Save();

			recentFileManager.Save();

			ProjectClosing();

			Trace.Listeners.Remove( harnessitListener );
		}

		private void OnSaveLog(object sender, EventArgs e)
		{
			// must be interactive...
			DialogResult dr;

			dr = saveFileDialogLogs.ShowDialog();
			if ( dr == DialogResult.OK )
			{
				string filename = saveFileDialogLogs.FileName;
				string extension = Path.GetExtension( filename ).Replace( ".", "" );
				ReportFormat format = (saveFileDialogLogs.FilterIndex == 1 ? ReportFormat.RTF : ReportFormat.XML);

				if ( extension == String.Empty )
				{
					if ( format == ReportFormat.RTF )
					{
						//filename += ".rtf";
						// TODO: fix for new ui.
						MessageBox.Show("RTF format not currently supported.");
					}
					else if ( format == ReportFormat.XML )
					{
						filename += ".xml";
					}
				}

				try
				{
					SaveLog( filename, format );
				}
				catch ( Exception ex )
				{
					MessageBox.Show( "Error saving test report.\n\n" + ex.Message, "HarnessIt Error",
					                 MessageBoxButtons.OK, MessageBoxIcon.Error );
				}
			}
		}

		private void SaveLog(string filename, ReportFormat format)
		{
			switch ( format )
			{
				case ReportFormat.XML:
					SaveXmlLog( filename );
					break;
				default:
					SaveRtfLog( filename );
					break;
			}
		}

		private void SaveRtfLog(string file)
		{
			// TODO: FIX for new ui.
			//Cursor c = this.Cursor;
			//try
			//{
			//	this.Cursor = Cursors.WaitCursor;
			//	this.statusBarMain.Text = "Generating a Rich Text report, please wait...";
			//	// Generate the complete "summary" info.
			//	ReportTests();

			//	SaveLogForm form =
			//		new SaveLogForm( file, rtCompReportDetails, rtCompLog, rtCompFailures, harnessitListener.RichTextComp );
			//	form.Show();

			//	Assembly[] assembliesArray = new Assembly[this.Assemblies.Count];
			//	this.Assemblies.CopyTo( assembliesArray );

			//	if ( form.e != null )
			//	{
			//		throw form.e;
			//	}
			//}
			//finally
			//{
			//	this.statusBarMain.Text = "";
			//	this.Cursor = c;
			//}
		}

		private void SaveXmlLog(string file)
		{
			Cursor c = this.Cursor;
			try
			{
				this.Cursor = Cursors.WaitCursor;
				this.statusBarMain.Text = "Generating an XML report, please wait...";

				Assembly[] assembliesArray = new Assembly[this.Assemblies.Count];
				this.Assemblies.CopyTo( assembliesArray );

				XmlLog.Write( file, GetPerformanceDetails(), this.proj, assembliesArray, iTestEngine, this.harnessitListener );
			}
			finally
			{
				this.statusBarMain.Text = "";
				this.Cursor = c;
			}
		}

		private void OnShowClassView(object sender, EventArgs e)
		{
			tabControlTreeViews.SelectedTab = tabPageClassView;
		}

		private void OnShowProjectView(object sender, EventArgs e)
		{
			tabControlTreeViews.SelectedTab = tabPageSolutionView;
		}

		private void OnAfterSelectClassView(object sender, TreeViewEventArgs e)
		{
			try
			{
				if ( e.Node == null )
				{
					return;
				}

				switch ( CountBackslashes( e.Node.FullPath ) )
				{
					case 1:
						ReportTests( GetAssembly( e.Node ) );
						break;
					case 2:
						ReportTests( GetClass( e.Node ) );
						break;
					case 3:
						ReportTests( GetMethod( e.Node ) );
						break;
					default:
						ReportTests();
						break;
				}

				// TODO: Fix for new UI.
				//tabControlReports.SelectedTab = tabPageReportExplorer;
			}
			catch ( Exception ex )
			{
				string msg = "An unexpected error has occurred. Please contact United Binary\r\n" +
				             "at support@unitedbinary with the information listed below (please copy it).";

				DetailedErrorForm.Show( msg, ex.Message + "\r\n\r\nFull exception:\r\n\r\n" + ex );
			}
		}

		private bool CheckCloseProject()
		{
			SyncProjectToForm( proj );

			if ( proj.Changed == false || !SystemInformation.UserInteractive )
			{
				return true;
			}

			//
			// Don't ask this question for new projects.
			//
			if ( proj.Name == "New Project" && proj.AssemblyCount == 0 )
			{
				return true;
			}

			// this should only happen if the project is modified (which shouldn't happen during unattended runs)...
			string msg = "";
			msg = "Save changes to the current project: " + proj.Name + "?";
			DialogResult dr = MessageBox.Show( msg, "HarnessIt", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question );
			if ( dr == DialogResult.Cancel )
			{
				return false;
			}
			else if ( dr == DialogResult.Yes )
			{
				OnSaveProject( null, null );

				// This will still be true if they cancel or fail to save the project.
				if ( proj.Changed == true )
				{
					return false;
				}
			}

			return true;
		}

		private void OnNewProject(object sender, EventArgs e)
		{
			if ( !CheckCloseProject() )
			{
				return;
			}

			ProjectClosing();
			proj = new TestProject();

			ProjectOpened();
		}

		private void OnLoadProject(object sender, EventArgs e)
		{
			// must be interactive...
			try
			{
				if ( !CheckCloseProject() )
				{
					return;
				}

				DialogResult dres = openFileDialogProject.ShowDialog();
				if ( dres == DialogResult.OK )
				{
					LoadProject( openFileDialogProject.FileName );
				}
			}
			catch ( Exception ex )
			{
				DetailedErrorForm.Show( "An error occurred while loading the project.",
				                        ex.Message + "\r\n\r\nMore information:\r\n" + ex );
			}
		}

		private void LoadProject(string file)
		{
			TestProject project = new TestProject();
			try
			{
				project.Load( file );
				LocalizeTestAssemblies( project );
				InitializeProjectExecutionEngine( project );

				ProjectClosing();
				proj = project; // proj is our class level project variable.
				ProjectOpened();
			}
			catch ( Exception ex )
			{
				string msg = "";
				if ( ex.Message == "There is invalid data at the root level. Line 1, position 1." )
				{
					msg = "Error loading project. It seems that this is an older " +
					      "HarnessIt test project used by the beta versions of HarnessIt. " +
					      "This version uses an incompatible format.  You will need to " +
					      "create a new project file. Sorry for the inconvinience.";
				}
				else
				{
					msg = "Error loading project.";
				}

				throw new Exception( msg, ex );
			}
		}

		private void InitializeProjectExecutionEngine(TestProject tp)
		{
			try
			{
				iTestEngine = testEngineEnumerator.GetEngine( tp.ExecutionEngine );
				iTestEngine.LoadSettings( tp.EngineSettings );
			}
			catch ( Exception e )
			{
				string msg = "Error intializing test execution engine \"" + tp.ExecutionEngine +
				             "\" specified by the project. The default engine will be used.";

				DetailedErrorForm.Show( msg, e.ToString() );
			}
		}

		private void OnSaveProject(object sender, EventArgs e)
		{
			if ( proj.FullPathName == "" )
			{
				SaveProjectAs();
				return;
			}

			try
			{
				SyncConfigFromProject( proj.Config );
				SyncProjectToForm( proj );
				proj.Save( proj.FullPathName );
				this.Text = AppTitle + " - [" + proj.Name + "]";

				// This needs to be called manually here as opposed to firing the
				// ProjectOpening/ProjectClosing events because neither really apply
				// and we still need to add this to the recent files.
				recentFileManager.Add( saveFileDialogProject.FileName );
			}
			catch ( Exception exp )
			{
				DetailedErrorForm.Show( "Error saving project.", exp.ToString() );
			}
		}

		private void SaveProjectAs()
		{
			// must be interactive...
			saveFileDialogProject.FileName = proj.Name;
			saveFileDialogProject.InitialDirectory = proj.FullPathName;

			DialogResult dres = saveFileDialogProject.ShowDialog();
			if ( dres == DialogResult.OK )
			{
				proj = new TestProject();
				SyncProjectToForm( proj );
				try
				{
					SyncConfigFromProject( proj.Config );
					proj.Save( saveFileDialogProject.FileName );

					this.Text = AppTitle + " - [" + proj.Name + "]";
					ReportTests();

					// This needs to be called manually here as opposed to firing the
					// ProjectOpening/ProjectClosing events because neither really apply
					// and we still need to add this to the recent files.
					recentFileManager.Add( saveFileDialogProject.FileName );
				}
				catch ( Exception exp )
				{
					DetailedErrorForm.Show( "Error saving project.", exp.ToString() );
				}
			}
		}

		private void menuItemSaveProjectAs_Click(object sender, EventArgs e)
		{
			SaveProjectAs();
		}

		private void SyncConfigFromProject(TestProjectConfig config)
		{
			config.ClearNodes();
			foreach ( Assembly A in Assemblies )
			{
				if ( A.ContainsTests )
				{
					string assemblyNodePath = "\\" + A.Name;
					config.AddNode( assemblyNodePath, A.Active );
					foreach ( Class C in A.Classes )
					{
						if ( C.ContainsTests )
						{
							string classNodePath = assemblyNodePath + "\\" + C.Name;
							config.AddNode( classNodePath, C.Active );
							foreach ( Method m in C.Methods )
							{
								config.AddNode( classNodePath + "\\" + m.Name, m.Active );
							}
						}
					}
				}
			}
		}

		private void SyncProjectFromConfig(TestProjectConfig config)
		{
			foreach ( Assembly A in Assemblies )
			{
				string assemblyNodePath = "\\" + A.Name;
				if ( config.ContainsNode( assemblyNodePath ) )
				{
					A.Active = config.GetNode( assemblyNodePath ).Enabled && A.ContainsOnlyRequiredTests == false;
				}
				foreach ( Class C in A.Classes )
				{
					string classNodePath = assemblyNodePath + "\\" + C.Name;
					if ( config.ContainsNode( classNodePath ) )
					{
						C.Active = config.GetNode( classNodePath ).Enabled && C.ContainsOnlyRequiredTests == false;
					}
					foreach ( Method m in C.Methods )
					{
						string methodNodePath = classNodePath + "\\" + m.Name;
						if ( config.ContainsNode( methodNodePath ) )
						{
							//
							// This may seem backwards, but we don't want the required tests checked even
							// if they are enabled. So we have to explicitly uncheck the required test methods.
							//
							m.Active = m.TestRequired == false && config.GetNode( methodNodePath ).Enabled;
						}
					}
				}
			}
		}

		/// <summary>
		///		Clears out the current views and re-initializes them to the new project.
		/// </summary>
		/// <param name="proj">The new project to load into the form.</param>
		private void SyncFormToProject(TestProject proj)
		{
			Assemblies.Clear();
			foreach ( string file in proj.AssemblyNames )
			{
				try
				{
					Assembly A = new Assembly( file );
					Assemblies.Add( A );
				}
				catch ( InconsistentTestBasisException e )
				{
					string msg = e.Message;
					string details = "The test basis assembly associated with \"" + file + "\" appears to be " +
					                 "out of date. Please update the associated test basis assembly " +
					                 "(UnitedBinary.UnitTests.Framework.TestBais.dll) with the latest " +
					                 "version distributed with HarnessIt. Usually, recompiling your project will automatically " +
					                 "update your test basis assembly, but sometimes recoding me be necessary if the test basis has " +
					                 "changed drastically.";

					DetailedErrorForm.Show( msg, details );
					Debug.WriteLine( "Exception message: " + e.ToString() );
				}
				catch ( Exception e )
				{
					string msg = "An error has occurred when loading project \"" + proj.Name + "\". ";
					msg += "The assembly " + file + " could not be loaded.";
					string details = e.Message;

					DetailedErrorForm.Show( msg, details );
					Debug.WriteLine( "Exception message: " + e.ToString() );
				}
			}

			Assemblies.Sort();

			PopulateTreeSolutionView();
			PopulateTreeClassView();
			this.Text = AppTitle + " - [" + proj.Name + "]";
		}

		/// <summary>
		///		Populates the project with the currently loaded assemblies.
		///		Used in saving projects.
		/// </summary>
		/// <param name="proj">Project to fill.</param>
		private void SyncProjectToForm(TestProject proj)
		{
			proj.ExecutionEngine = iTestEngine.GetType().ToString();
			proj.EngineSettings = iTestEngine.GetSettings();

//			if (Assemblies.Count == 0)
//			{
//				return;
//			}

			string[] names = new string[Assemblies.Count];
			for ( int i = 0; i < Assemblies.Count; i++ )
			{
				Assembly A = (Assembly)Assemblies[i];
				names[i] = A.FullPathName;
			}

			proj.AssemblyNames = names;
		}

		private void OnExit(object sender, EventArgs e)
		{
			Close();
		}

		private void OnAddAssembly(object sender, EventArgs e)
		{
			// must be interactive...
			if ( openFileDialogAssam.ShowDialog() == DialogResult.OK )
			{
				AddAssembly( openFileDialogAssam.FileName );
			}
		}

		private void AddAssembly(string file)
		{
			Assembly A = null;
			try
			{
				A = new Assembly( file );
			}
			catch ( BadImageFormatException be )
			{
				string msg = "";
				msg = "This file does not appear to be a vaild .NET assembly.\r\n";
				msg += "Filename: " + file + ".";

				DetailedErrorForm.Show( msg, be.ToString() );

				return;
			}
			catch ( Exception e )
			{
				string msg = "";
				if ( e.Message.IndexOf( "IComparer" ) >= 0 )
				{
					msg = "Inconsistent test basis DLL error.";
					string details = "The test basis DLL associated with the assembly \"" + file + "\" appears to be " +
					                 "out of date. Please update the associated test basis DLL " +
					                 "(UnitedBinary.UnitTests.Framework.TestBais.dll) with the latest " +
					                 "version distributed with HarnessIt.";

					DetailedErrorForm.Show( msg, details );
					return;
				}

				msg = "An error has occurred while loading assembly.\r\n";
				msg += "Filename: " + file + ".";

				DetailedErrorForm.Show( msg, e.Message );
				return;
			}

			if ( A == null )
			{
				return; // shouldn't happen, but ...
			}

			// Don't load the same one twice.
			foreach ( Assembly B in Assemblies )
			{
				if ( B.FullPathName == A.FullPathName )
				{
					string msg = "This assembly is already loaded in the current project. ";
					msg += "It cannot be loaded twice.\r\n\r\n";
					msg += "Filename:\r\n";
					msg += file;
					if ( SystemInformation.UserInteractive )
					{
						MessageBox.Show( msg, "HarnessIt Error", MessageBoxButtons.OK, MessageBoxIcon.Error );
					}
					else
					{
						EmergencyLog.WriteLine( "Attempt to load assembly twice.", msg );
					}
					return;
				}
			}

			Assemblies.Add( A );
			SyncProjectToForm( this.proj );

			PopulateTreeClassView();
			PopulateTreeSolutionView();

			try
			{
				StringCollection blockedFiles = new StringCollection();
				LocalizeSingleAssembly( A.FullPathName, blockedFiles );

				if ( blockedFiles.Count > 0 )
				{
					if ( SystemInformation.UserInteractive )
					{
						string[] files = new string[blockedFiles.Count];
						blockedFiles.CopyTo( files, 0 );

						LocalizationWarningForm frm = new LocalizationWarningForm();
						frm.BlockedFiles = files;

						frm.ShowDialog();
					}
					else
					{
						string lockedFiles = "";
						for ( int i = 0; i < blockedFiles.Count; i++ )
						{
							lockedFiles += (i > 0 ? ", " : "") + blockedFiles[i];
						}
						EmergencyLog.WriteLine( "Local assemblies locked.", lockedFiles );
					}
				}
			}
			catch ( Exception e )
			{
				string msg = "Error localizing assemblies.";
				DetailedErrorForm.Show( msg, e.ToString(), DetailedErrorTypes.Warning );
			}
		}

		private void OnRunTests(object sender, EventArgs e)
		{
			Cursor cursor = this.Cursor;
			this.Cursor = Cursors.WaitCursor;

			if ( ContainsActiveTests || ContainsRequiredTests )
			{
				RunTests();
			}
			else
			{
				if ( SystemInformation.UserInteractive )
				{
					MessageBox.Show( "There are no active tests.  Select some unit tests to run.", "HarnessIt Error",
					                 MessageBoxButtons.OK, MessageBoxIcon.Information );
				}
				else
				{
					EmergencyLog.WriteLine( "No tests selected.", "No tests will be performed." );
				}
			}

			this.Cursor = cursor;
		}

		private void OnHelpAbout(object sender, EventArgs e)
		{
			// must be interactive to get this...
			AboutForm dlg = new AboutForm();
			dlg.ShowDialog();
		}

		private void OnCheck(object sender, TreeViewEventArgs e)
		{
			// Stupid thing seems to be calling itself twice.  Once from the event fired
			// when the user clicks and once from when we toggle the settings.  This creates
			// a DEEP depth recursion (clearly BAD!).  This little "checking" hack
			// stops the second call and fixes the problem.
			if ( CatchFalseChecking )
			{
				return;
			}

			Cursor cursor = this.Cursor;

			try
			{
				CatchFalseChecking = true;
				this.Cursor = Cursors.WaitCursor;

				//if (IsRequiredMethod(e.Node))
				if ( TreeNodeContainsOnlyRequiredSubNodes( e.Node ) )
				{
					e.Node.Checked = false;
					return;
				}

				if ( IsTest( e.Node ) )
				{
					SetClassTreeNodeCheck( e.Node );
					BubbleClassViewStatesUp( e.Node );
				}
				else
				{
					e.Node.Checked = false;
				}

				TreeNode rootNode = treeViewClasses.Nodes[0];
				SyncEnabledStates( rootNode );
			}
			catch ( Exception ex )
			{
				string msg = "An unexpected error has occurred. Please contact United Binary\r\n" +
				             "at support@unitedbinary with the information listed below (please copy it).";

				DetailedErrorForm.Show( msg, "Message:\r\n" + ex.Message + "\r\nFull exception:\r\n\r\n" + ex );
			}
			finally
			{
				CatchFalseChecking = false;
				this.Cursor = cursor;
			}
		}

		/// <summary>
		///		Takes the checked state of node n and then
		///		considers the parents, unchecking them if
		///		they no longer have any checked children.
		/// </summary>
		/// <param name="n">Node to start moving up at.</param>
		private void BubbleClassViewStatesUp(TreeNode n)
		{
			if ( n.Parent == null )
			{
				return;
			}

			TreeNode p = n.Parent;

			bool checkedState = false;
			foreach ( TreeNode e in p.Nodes )
			{
				checkedState = checkedState || e.Checked;
			}

			p.Checked = checkedState;
			BubbleClassViewStatesUp( p );
		}

		private bool TreeNodeContainsOnlyRequiredSubNodes(TreeNode n)
		{
			Method m = n.Tag as Method;
			if ( m != null )
			{
				return m.TestRequired;
			}

			Class c = n.Tag as Class;
			if ( c != null )
			{
				return c.ContainsOnlyRequiredTests;
			}

			Assembly A = n.Tag as Assembly;
			if ( A != null )
			{
				return A.ContainsOnlyRequiredTests;
			}

			return false;
		}

		private void OnKeyDownSolView(object sender, KeyEventArgs e)
		{
			if ( e.KeyCode == Keys.Delete )
			{
				RemoveAssembly( true );
			}
			else if ( e.KeyCode == Keys.Insert )
			{
				OnAddAssembly( sender, null );
			}
		}

		// this method requires interactivity to run...
		private void RemoveAssembly(bool interact)
		{
			TreeNode n = treeViewSolution.SelectedNode;
			if ( n != null )
			{
				Assembly A = GetAssembly( n );
				if ( A != null )
				{
					if ( interact )
					{
						string q = "Remove assembly \"" + A.Name + "\" from the project?";
						DialogResult dr = MessageBox.Show( this, q, "Remove Assembly", MessageBoxButtons.YesNo );
						if ( dr != DialogResult.Yes )
						{
							return;
						}
					}

					for ( int i = 0; i < Assemblies.Count; i++ )
					{
						Assembly B = (Assembly)Assemblies[i];
						if ( A.Name == B.Name )
						{
							Assemblies.Remove( Assemblies[i] );
							PopulateTreeClassView();
							PopulateTreeSolutionView();

							TreeNode rootNode = treeViewClasses.Nodes[0];
							SyncEnabledStates( rootNode );
							SyncProjectToForm( this.proj );
						}
					}
					return;
				}
			}

			MessageBox.Show( "The selected item cannot be removed. Please select an assembly.", "HarnessIt",
			                 MessageBoxButtons.OK, MessageBoxIcon.Information );
		}

		private void OnProjectViewMouseUp(object sender, MouseEventArgs e)
		{
			if ( e.Button == MouseButtons.Right )
			{
				TreeNode n = treeViewSolution.GetNodeAt( e.X, e.Y );
				if ( n == null )
				{
					mnuClassView.Show( (Control)sender, new Point( e.X, e.Y ) );
				}
				else
				{
					treeViewSolution.SelectedNode = n;
					mnuProjectView.Show( (Control)sender, new Point( e.X, e.Y ) );
				}
			}
		}

		private void OnRemoveAssembly(object sender, EventArgs e)
		{
			RemoveAssembly( true );
		}

		#endregion

		#region Data and Tree synchronization methods

		protected void SetClassTreeNodeCheck(TreeNode N)
		{
			bool shouldCheck = true;
			for ( int i = 0; i < N.Nodes.Count; i++ )
			{
				//shouldCheck = IsTest(N.Nodes[i]) && !IsRequiredMethod(N.Nodes[i]);
				shouldCheck = IsTest( N.Nodes[i] ) && !TreeNodeContainsOnlyRequiredSubNodes( N.Nodes[i] );
				N.Nodes[i].Checked = (N.Checked && shouldCheck);

				if ( shouldCheck )
				{
					SetClassTreeNodeCheck( N.Nodes[i] );
				}
			}
		}

		/// <summary>
		///		Determines whether a tree node is a test node.
		/// </summary>
		/// <param name="n">Node to test.</param>
		/// <returns>true if it is a test, false othewise.</returns>
		private bool IsTest(TreeNode n)
		{
			Class c = n.Tag as Class;
			if ( c != null )
			{
				return c.ContainsTests;
			}

			Assembly a = n.Tag as Assembly;
			if ( a != null )
			{
				return a.ContainsTests;
			}

			return true; // it's a method...
		}

		/// <summary>
		///		Gets the Assembly object corresponding to the tree node.
		/// </summary>
		/// <param name="treePath">Tree node path.</param>
		/// <returns>Assembly corresponding to tree node.</returns>
		protected Assembly GetAssembly(TreeNode node)
		{
			return (Assembly)node.Tag;
		}

		/// <summary>
		///		Gets the Class object corresponding to the tree node.
		/// </summary>
		/// <param name="treePath">Tree node path.</param>
		/// <returns>Class corresponding to the tree node.</returns>
		protected Class GetClass(TreeNode node)
		{
			return (Class)node.Tag;
		}

		/// <summary>
		///		Gets the Method object corresponding to the tree node.
		/// </summary>
		/// <param name="treePath">Tree node path.</param>
		/// <returns>Method object corresponding to the tree node.</returns>
		protected Method GetMethod(TreeNode node)
		{
			return (Method)node.Tag;
		}


		/// <summary>
		///		Sets the enabled states of the Assemblies, Classes, and Methods
		///		to be the same as the corresponding tree checked states.
		/// </summary>
		/// <param name="node">Node to sync.</param>
		protected void SyncEnabledStates(TreeNode node)
		{
			foreach ( TreeNode n in node.Nodes )
			{
				string path = n.FullPath;
				switch ( CountBackslashes( path ) )
				{
					case 1: // Assembly
						GetAssembly( n ).Active = n.Checked;
						break;
					case 2: // Class
						GetClass( n ).Active = n.Checked;
						break;
					case 3: // Method
						GetMethod( n ).Active = n.Checked;
						break;
					default:
						return;
				}

				SyncEnabledStates( n );
			}
		}

		protected int CountBackslashes(string text)
		{
			int c = 0;
			int len = text.Length;
			for ( int i = 0; i < len; i++ )
			{
				if ( text[i] == '\\' )
				{
					c++;
				}
			}
			return c;
		}

		protected void SyncClassTreeEnabledStatesFromConfig(TreeNode node, TestProjectConfig config)
		{
			foreach ( TreeNode n in node.Nodes )
			{
				string path = n.FullPath;
				int trimmer = 0;
				int pathLength = path.Length;
				for ( int i = 0; i < pathLength; i++ )
				{
					if ( path[i] == '\\' )
					{
						trimmer = i;
						break;
					}
				}

				path = path.Substring( trimmer );
				if ( config.ContainsNode( path ) )
				{
					switch ( CountBackslashes( path ) )
					{
						case 1:
							{
								Assembly A = GetAssembly( n );
								A.Active = config.GetNode( path ).Enabled;
								n.Checked = A.Active && A.ContainsOnlyRequiredTests == false;
								break;
							}
						case 2:
							{
								Class C = GetClass( n );
								C.Active = config.GetNode( path ).Enabled;
								n.Checked = C.Active && C.ContainsTests && C.ContainsOnlyRequiredTests == false;
								break;
							}
						case 3:
							{
								Method m = GetMethod( n );
								m.Active = config.GetNode( path ).Enabled;
								n.Checked = m.Active && m.TestRequired == false;

								//
								// If this node is check, ensure the parents are checked.
								//
								if ( n.Checked == true )
								{
									TreeNode parent = n.Parent;
									while ( parent != null )
									{
										parent.Checked = true;
										parent = parent.Parent;
									}
								}
								break;
							}
					}
				}
				else
				{
					switch ( CountBackslashes( path ) )
					{
						case 1:
							{
								Assembly A = GetAssembly( n );
								n.Checked = A.Active && A.ContainsTests;
								break;
							}
						case 2:
							{
								Class C = GetClass( n );
								n.Checked = C.Active && C.ContainsTests;
								break;
							}
						case 3:
							{
								Method m = GetMethod( n );
								n.Checked = m.Active;
								break;
							}
					}

					if ( n.Checked )
					{
						SyncNodeParents( n.Parent );
					}
				}

				SyncClassTreeEnabledStatesFromConfig( n, config );
			}
		}

		/// <summary>
		///		SyncNodeParents is built to handle the following case.
		///		Suppose you have a project that has been loaded into HarnessIt.
		///		Next you add a new class which is not a test class to an
		///		assembly in the project.  Next time you run HarnessIt, this will
		///		appear unchecked in the ClassView Tree as it should.  But, now
		///		add a test method to this class.  When you run HarnessIt again,
		///		this class will be unchecked, but the method will be checked!
		///		
		///		SyncNodeParents traverses up the ClassView tree correcting this
		///		issue when new items come into the project as described above.
		/// </summary>
		/// <param name="n">TreeNode whos parents need synced with n.</param>
		private void SyncNodeParents(TreeNode n)
		{
			// If null, we are at the top, quit.
			if ( n == null )
			{
				return;
			}

			// If checked already, no need check child nodes.
			if ( n.Checked )
			{
				SyncNodeParents( n.Parent );
				return;
			}

			// Check for any enabled child nodes.
			bool check = false;
			foreach ( TreeNode p in n.Nodes )
			{
				if ( p.Checked == true )
				{
					check = true;
				}
			}

			// Set the check according to children and move on
			// to the parent node.
			n.Checked = check;
			SyncNodeParents( n.Parent );
		}

		#endregion

		#region TreeView coloring functions

		/// <summary>
		///		Sets the color of the Class View tree to correspond to the test results.
		/// </summary>
		/// <param name="node">Tree node to color.</param>
		private void ColorTreeClassView(TreeNode node)
		{
			TreeNodeCollection nodeCollection = node.Nodes;
			foreach ( TreeNode n in nodeCollection )
			{
				string path = n.FullPath;
				switch ( CountBackslashes( path ) )
				{
					case 1: // Assembly
						n.ForeColor = GetIdleColor( GetAssembly( n ) );
						break;
					case 2: // Class
						n.ForeColor = GetIdleColor( GetClass( n ) );
						break;
					case 3: // Method
						n.ForeColor = GetIdleColor( GetMethod( n ) );
						break;
					default:
						return;
				}

				ColorTreeClassView( n );
			}
		}

		private void AutoClassViewUpdate()
		{
			while ( AutoClassViewContinue )
			{
				// TODO: THREAD FIX
				//this.BeginInvoke( new EventHandler( delegate
				{
					//uint WM_SETREDRAW = 11;
					//try
					//{
					//    //SendMessage((System.IntPtr)treeViewClasses.Handle, WM_SETREDRAW, 0, 0);

					//    treeViewClasses.BeginUpdate();
					//    ColorTreeClassView( treeViewClasses.Nodes[0] );
					//}
					//finally
					//{
					//    //SendMessage((System.IntPtr)treeViewClasses.Handle, WM_SETREDRAW, 1, 0);
					//    treeViewClasses.EndUpdate();
					//}
					Thread.Sleep( 125 );
				}// ) );
			}
		}

		private bool AutoClassViewContinue
		{
			get
			{
				lock ( treeViewClasses )
				{
					return autoClassViewContinue;
				}
			}
			set
			{
				lock ( treeViewClasses )
				{
					autoClassViewContinue = value;
				}
			}
		}

		private Color GetIdleColor(Method m)
		{
			if ( m.HasRun )
			{
				if ( m.TestRecord.Failures == 0 )
				{
					return GetNodeColor( TestStates.Passed );
				}
				else
				{
					return GetNodeColor( TestStates.Failed );
				}
			}
			else
			{
				return GetNodeColor( TestStates.NotRunYet );
			}
		}

		private Color GetIdleColor(Class c)
		{
			bool test = c.ContainsTests;
			if ( test && c.TestRecord.HasRun )
			{
				if ( c.TestRecord.Failures == 0 )
				{
					return GetNodeColor( TestStates.Passed );
				}
				else
				{
					return GetNodeColor( TestStates.Failed );
				}
			}
			else if ( test )
			{
				return GetNodeColor( TestStates.NotRunYet );
			}
			else
			{
				return GetNodeColor( TestStates.NotATest );
			}
		}

		private Color GetIdleColor(Assembly A)
		{
			bool test = A.ContainsTests;
			if ( test && A.TestRecord.HasRun )
			{
				if ( A.TestRecord.Failures == 0 )
				{
					return GetNodeColor( TestStates.Passed );
				}
				else
				{
					return GetNodeColor( TestStates.Failed );
				}
			}
			else if ( test )
			{
				return GetNodeColor( TestStates.NotRunYet );
			}
			else
			{
				return GetNodeColor( TestStates.NotATest );
			}
		}

		private Color GetNodeColor(TestStates state)
		{
			switch ( state )
			{
				case TestStates.Failed:
					return Color.Red;
				case TestStates.Passed:
					return Color.Blue;
				case TestStates.NotATest:
					return Color.Gray;
				case TestStates.NotRunYet:
					return Color.Black;
			}

			return new Color();
		}

		#endregion

		#region Tree populating functions

		private void PopulateTreeSolutionView()
		{
			treeViewSolution.Nodes.Clear();
			TreeNode rootNode = new TreeNode( "Project Assemblies", 1, 1 );
			treeViewSolution.Nodes.Add( rootNode );

			foreach ( Assembly A in Assemblies )
			{
				TreeNode Anode = new TreeNode( A.Name, 0, 0 );
				Anode.Tag = A;
				rootNode.Nodes.Add( Anode );
			}
			treeViewSolution.ExpandAll();
		}

		private void PopulateTreeClassView()
		{
			treeViewClasses.Nodes.Clear();

			TreeNode allTestNode = new TreeNode( "Project Assemblies", 1, 2 );
			allTestNode.Checked = true;
			treeViewClasses.BeginUpdate();

			treeViewClasses.Nodes.Add( allTestNode );

			foreach ( Assembly A in Assemblies )
			{
				if ( A.ContainsTests )
				{
					TreeNode Anode = new TreeNode( A.Name, 1, 2 );
					Anode.Checked = A.ContainsTests && (A.ContainsOnlyRequiredTests == false);
					Anode.Tag = A;
					if ( A.ContainsRequiredTests )
					{
						Anode.BackColor = Color.PaleGoldenrod;
					}

					foreach ( Class c in A.Classes )
					{
						if ( c.ContainsTests )
						{
							TreeNode Cnode = new TreeNode( c.Name, 0, 1 );
							Cnode.Checked = (c.TestCount > 0) && (c.ContainsOnlyRequiredTests == false);
							Cnode.Tag = c;
							if ( c.ContainsRequiredTests )
							{
								Cnode.BackColor = Color.PaleGoldenrod;
							}

							foreach ( Method m in c.Methods )
							{
								TreeNode Mnode = new TreeNode( m.Name, 1, 0 );
								if ( m.TestRequired )
								{
									Mnode.Checked = false;
									Mnode.BackColor = Color.PaleGoldenrod;
								}
								else
								{
									Mnode.Checked = true;
								}
								Mnode.Tag = m;

								Cnode.Nodes.Add( Mnode );
							}
							Anode.Nodes.Add( Cnode );
						}
					}
					allTestNode.Nodes.Add( Anode );
					Anode.Expand();
				}
			}

			treeViewClasses.EndUpdate();

			ColorTreeClassView( treeViewClasses.Nodes[0] );
			treeViewClasses.Nodes[0].Expand();
			treeViewClasses.SelectedNode = treeViewClasses.Nodes[0];
		}

		#endregion

		#region Test execution and reporting

		private void ReportTests(Assembly A)
		{
			// TODO: Fix for new UI.

			//Cursor cursor = this.Cursor;
			//try
			//{
			//	this.Cursor = Cursors.WaitCursor;
			//	this.statusBarMain.Text = AnalyzingStatusText;

			//	rtCompReportDetails.Clear();

			//	ReportFormatter.ReportTests( A, proj, rtCompReportDetails, this.harnessitListener );

			//	rtCompReportDetails.Render();

			//	//
			//	// Scroll back to the top of the text box, it automatically
			//	// scrolls to the bottom.
			//	//
			//	rtCompReportDetails.RichTextBox.Select( 0, 0 );
			//	rtCompReportDetails.RichTextBox.ScrollToCaret();
			//}
			//finally
			//{
			//	this.statusBarMain.Text = "";
			//	this.Cursor = cursor;
			//}
		}

		private void ReportTests(Class C)
		{
			// TODO: Fix for new UI.

			//Cursor cursor = this.Cursor;
			//try
			//{
			//	this.Cursor = Cursors.WaitCursor;
			//	this.statusBarMain.Text = AnalyzingStatusText;

			//	rtCompReportDetails.Clear();

			//	ReportFormatter.ReportTests( C, proj, rtCompReportDetails, this.harnessitListener );

			//	rtCompReportDetails.Render();

			//	//
			//	// Scroll back to the top of the text box, it automatically
			//	// scrolls to the bottom.
			//	//
			//	rtCompReportDetails.RichTextBox.Select( 0, 0 );
			//	rtCompReportDetails.RichTextBox.ScrollToCaret();
			//}
			//finally
			//{
			//	this.statusBarMain.Text = "";
			//	this.Cursor = cursor;
			//}
		}

		private void ReportTests(Method m)
		{
			// TODO: Fix for new UI.

			//Cursor cursor = this.Cursor;
			//try
			//{
			//	this.Cursor = Cursors.WaitCursor;
			//	this.statusBarMain.Text = AnalyzingStatusText;

			//	rtCompReportDetails.Clear();

			//	ReportFormatter.ReportTests( m, proj, rtCompReportDetails, this.harnessitListener );

			//	rtCompReportDetails.Render();

			//	//
			//	// Scroll back to the top of the text box, it automatically
			//	// scrolls to the bottom.
			//	//
			//	rtCompReportDetails.RichTextBox.Select( 0, 0 );
			//	rtCompReportDetails.RichTextBox.ScrollToCaret();
			//}
			//finally
			//{
			//	this.statusBarMain.Text = "";
			//	this.Cursor = cursor;
			//}
		}

		private void ReportTests()
		{
			// TODO: Fix for new UI.
			//Cursor cursor = this.Cursor;
			//try
			//{
			//	this.Cursor = Cursors.WaitCursor;

			//	try
			//	{
			//		treeViewClasses.BeginUpdate();
			//		ColorTreeClassView( treeViewClasses.Nodes[0] );
			//	}
			//	finally
			//	{
			//		treeViewClasses.EndUpdate();
			//	}

			//	treeViewClasses.SelectedNode = treeViewClasses.Nodes[0];

			//	rtCompReportDetails.Clear();

			//	ReportPerformanceDetails perf = GetPerformanceDetails();

			//	ReportFormatter.ReportTests( perf, proj, rtCompReportDetails );

			//	rtCompReportDetails.Render();
			//}
			//finally
			//{
			//	this.Cursor = cursor;
			//}
		}

		private void ReportFailures()
		{
			// TODO: Fix for new UI.

			//Cursor cursor = this.Cursor;
			//try
			//{
			//	this.Cursor = Cursors.WaitCursor;
			//	this.statusBarMain.Text = AnalyzingStatusText;

			//	rtCompFailures.Clear();
			//	rtCompFailures.Render();

			//	ReportFormatter.ReportFailures( Assemblies, proj, rtCompFailures );

			//	rtCompFailures.Render();
			//}
			//finally
			//{
			//	this.statusBarMain.Text = "";
			//	this.Cursor = cursor;
			//}
		}

		private ReportPerformanceDetails GetPerformanceDetails()
		{
			ReportPerformanceDetails perf = new ReportPerformanceDetails();

			TestMethodRecord TotalTMR = new TestMethodRecord();
			foreach ( Assembly A in Assemblies )
			{
				if ( A.ContainsActiveTests )
				{
					TotalTMR += A.TestRecord;
				}
			}

			perf.runningTime = runningTime.TotalSeconds;
			perf.AssemblyCount = AssemblyCount;
			perf.ClassCount = ClassCount;
			perf.MethodCount = MethodCount;
			perf.TestClassCount = TestClassCount;
			perf.TestMethodCount = TestMethodCount;
			perf.TotalRecord = TotalTMR;
			perf.executionTime = TotalExecutionTime;

			return perf;
		}

		/// <summary>
		///		RunTests runs all the active unit test methods.
		/// </summary>
		/// <param name="show">
		///		Determines whether to show the running tests form in the taskbar. 
		///		Sometimes we want to show this form (say before HarnessIt is visible)
		///		and sometimes we don't (when it is a modal dialog for HarnessIt).
		/// </param>
		private void RunTests()
		{
			ClearTestReportingControls();
			userCancelledTests = false;

			UpdateTreeColors();
			
			Cursor c = this.Cursor;
			try
			{
				testResultsControl.Clear();
				testResultsControl.TestsStarting();
				this.Cursor = Cursors.WaitCursor;
				this.statusBarMain.Text = "Executing unit tests";//, click STOP button or press <ESC> to cancel...";

				// TODO: Fix!
				Application.DoEvents();

				try
				{
					TestExecutor testExecutor = new TestExecutor(iTestEngine);
					Method[] activeMethods = testExecutor.GetAllActiveAndRequiredMethods(this.Assemblies.ToArray());

					testExecutor.MethodExecuted += (o, e) => testResultsControl.AddTestResult(e.Method);
					testExecutor.Run(activeMethods);
				}
				catch (Exception ex)
				{
					MessageBox.Show(ex.ToString());	
				}
				testResultsControl.RenderResults();
			}
			finally
			{
				this.Cursor = c;
				this.statusBarMain.Text = "";
			}

			ReportTests();
			ReportFailures();

			//if ( TestsFailed )
			//{
			//	tabControlReports.SelectedTab = tabPageFailures;
			//}

			UpdateTreeColors();
		}

		private void UpdateTreeColors()
		{
			try
			{
				//SendMessage((System.IntPtr)treeViewClasses.Handle, WM_SETREDRAW, 0, 0);

				treeViewClasses.BeginUpdate();
				ColorTreeClassView( treeViewClasses.Nodes[0] );
			}
			finally
			{
				//SendMessage((System.IntPtr)treeViewClasses.Handle, WM_SETREDRAW, 1, 0);
				treeViewClasses.EndUpdate();
				treeViewClasses.Invalidate(true);
				Application.DoEvents();

			}
		}

		private void ClearTestReportingControls()
		{
			testResultsControl.Clear();
//			this.harnessitListener.Clear();
		}

		private string EnginePath
		{
			get { return AppDomain.CurrentDomain.BaseDirectory + "bin\\Execution Engines"; }
		}

		#endregion

		#region Properties used to stop some events that aren't user triggered.

		private bool CatchFalseChecking { get; set; }

		#endregion

		#region Attributes for project statistics

		private double TotalExecutionTime
		{
			get
			{
				double dt = 0.0;
				foreach ( Assembly A in Assemblies )
				{
					dt += A.RunningTime;
				}

				return dt;
			}
		}

		private int AssemblyCount
		{
			get { return Assemblies.Count; }
		}

		private int ClassCount
		{
			get
			{
				int count = 0;
				foreach ( Assembly A in Assemblies )
				{
					count += A.ClassCount;
				}

				return count;
			}
		}

		private int TestClassCount
		{
			get
			{
				int count = 0;
				foreach ( Assembly A in Assemblies )
				{
					foreach ( Class c in A.Classes )
					{
						if ( c.ContainsTests )
						{
							count++;
						}
					}
				}

				return count;
			}
		}

		private int MethodCount
		{
			get
			{
				int count = 0;
				foreach ( Assembly A in Assemblies )
				{
					foreach ( Class c in A.Classes )
					{
						count += c.MethodCount;
					}
				}

				return count;
			}
		}

		private int TestMethodCount
		{
			get
			{
				int count = 0;
				foreach ( Assembly A in Assemblies )
				{
					foreach ( Class c in A.Classes )
					{
						count += c.TestCount;
					}
				}

				return count;
			}
		}

		private bool ContainsActiveTests
		{
			get
			{
				foreach ( Assembly A in Assemblies )
				{
					if ( A.ContainsActiveTests )
					{
						return true;
					}
				}

				return false;
			}
		}

		private bool ContainsRequiredTests
		{
			get
			{
				foreach ( Assembly A in Assemblies )
				{
					if ( A.ContainsRequiredTests )
					{
						return true;
					}
				}

				return false;
			}
		}


		internal bool TestsFailed
		{
			get
			{
				foreach ( Assembly A in Assemblies )
				{
					if ( A.TestRecord.Failures > 0 )
					{
						return true;
					}
				}

				return false;
			}
		}

		#endregion

		#region Assembly Localization

		private void LocalizeTestAssemblies(TestProject project)
		{
			Debug.WriteLine( "Creating local copies of assemblies..." );
			StringCollection blockedFiles = new StringCollection();

			string[] assemblyNames = project.AssemblyNames;
			foreach ( string s in assemblyNames )
			{
				try
				{
					LocalizeSingleAssembly( s, blockedFiles );
				}
				catch ( Exception e )
				{
					string msg = "Error localizing assemblies.";
					DetailedErrorForm.Show( msg, e.ToString(), DetailedErrorTypes.Warning );
				}
			}

			if ( blockedFiles.Count > 0 )
			{
				if ( SystemInformation.UserInteractive )
				{
					string[] files = new string[blockedFiles.Count];
					blockedFiles.CopyTo( files, 0 );

					LocalizationWarningForm frm = new LocalizationWarningForm();
					frm.BlockedFiles = files;

					frm.ShowDialog();
				}
				else
				{
					string lockedFiles = "";
					for ( int i = 0; i < blockedFiles.Count; i++ )
					{
						lockedFiles += (i > 0 ? ", " : "") + blockedFiles[i];
					}
					EmergencyLog.WriteLine( "Local assemblies locked.", lockedFiles );
				}
			}
		}

		private void CleanLocalTestAssemblyDir()
		{
			string assemblyTempDir = AppDomain.CurrentDomain.BaseDirectory + "AssemblyTemp\\";
			string[] files = Directory.GetFiles( assemblyTempDir, "*" );
			foreach ( string f in files )
			{
				try
				{
					Debug.WriteLine( "Removing " + Path.GetFileName( f ) + " from local assembly cache." );
					File.Delete( f );
				}
				catch ( Exception e )
				{
					Debug.WriteLine( "Error removing local assembly copy. Details: " + e );
				}
			}
		}

		private void LocalizeSingleAssembly(string assemblyFileName, StringCollection blockedFiles)
		{
			string assemblyTempDir = AppDomain.CurrentDomain.BaseDirectory + "AssemblyTemp\\";

			string[] dlls = Directory.GetFiles( Path.GetDirectoryName( assemblyFileName ), "*.dll" );
			string[] exes = Directory.GetFiles( Path.GetDirectoryName( assemblyFileName ), "*.exe" );
			string[] pdbs = Directory.GetFiles( Path.GetDirectoryName( assemblyFileName ), "*.pdb" );

			foreach ( string f in dlls )
			{
				if ( AssemblyNeedsLocalized( f ) )
				{
					try
					{
						string localFile = assemblyTempDir + Path.GetFileName( f );
						Debug.WriteLine( "Copying " + f + " to " + localFile );
						File.Copy( f, localFile, true );
					}
					catch
					{
						if ( !blockedFiles.Contains( f.ToLower() ) )
						{
							blockedFiles.Add( f.ToLower() );
						}
					}
				}
				else
				{
					Debug.WriteLine( "LocalizeAssembly() skipping up-to-date file: " + Path.GetFileName( f ) );
				}
			}

			foreach ( string f in exes )
			{
				if ( AssemblyNeedsLocalized( f ) )
				{
					try
					{
						string localFile = assemblyTempDir + Path.GetFileName( f );
						Debug.WriteLine( "Copying " + f + " to " + localFile );
						File.Copy( f, localFile, true );
					}
					catch
					{
						if ( !blockedFiles.Contains( f.ToLower() ) )
						{
							blockedFiles.Add( f.ToLower() );
						}
					}
				}
				else
				{
					Debug.WriteLine( "LocalizeAssembly() skipping up-to-date file: " + Path.GetFileName( f ) );
				}
			}

			foreach ( string f in pdbs )
			{
				if ( AssemblyNeedsLocalized( f ) )
				{
					try
					{
						string localFile = assemblyTempDir + Path.GetFileName( f );
						Debug.WriteLine( "Copying " + f + " to " + localFile );
						File.Copy( f, localFile, true );
					}
					catch
					{
						if ( !blockedFiles.Contains( f.ToLower() ) )
						{
							blockedFiles.Add( f.ToLower() );
						}
					}
				}
				else
				{
					Debug.WriteLine( "LocalizeAssembly() skipping up-to-date file: " + Path.GetFileName( f ) );
				}
			}
		}

		private bool AssemblyNeedsLocalized(string originalAssemblyFileName)
		{
			string assemblyTempDir = AppDomain.CurrentDomain.BaseDirectory + "AssemblyTemp\\";
			string localFile = assemblyTempDir + Path.GetFileName( originalAssemblyFileName );

			FileInfo oFI = new FileInfo( originalAssemblyFileName );
			FileInfo lFI = new FileInfo( localFile );

			if ( lFI.Exists == false )
			{
				return true;
			}

			bool needsUpdate = false;
			needsUpdate = needsUpdate || (lFI.LastWriteTime != oFI.LastWriteTime);
			needsUpdate = needsUpdate || (lFI.Length != oFI.Length);

			return needsUpdate;
		}

		#endregion

		#region Navigation Related Code

		private void NavigateBackward()
		{
			// TODO: Fix for new UI.

			//if ( historyIndex > 0 )
			//{
			//	ignoreTabSelection = true;
			//	tabControlReports.SelectedIndex = (int)history[--historyIndex];
			//	ignoreTabSelection = false;

			//	//Debug.WriteLine("*** History Index: " + historyIndex + ", History Count: " + history.Count);
			//	UpdateNavigationEnabledStates();
			//}
		}

		private void NavigateForward()
		{
			// TODO: Fix for new UI.

			//if ( historyIndex < history.Count - 1 )
			//{
			//	ignoreTabSelection = true;
			//	tabControlReports.SelectedIndex = (int)history[++historyIndex];
			//	ignoreTabSelection = false;

			//	//Debug.WriteLine("*** History Index: " + historyIndex + ", History Count: " + history.Count);
			//	UpdateNavigationEnabledStates();
			//}
		}

		private void AllControls_MouseDown(object sender, MouseEventArgs e)
		{
			if ( e.Button == MouseButtons.XButton1 )
			{
				NavigateBackward();
			}
			else if ( e.Button == MouseButtons.XButton2 )
			{
				NavigateForward();
			}
		}

		private void SetupMouseDownEvents(Control c)
		{
			c.MouseDown += this.AllControls_MouseDown;
			if ( c != null && c.Controls != null )
			{
				foreach ( Control ctrl in c.Controls )
				{
					SetupMouseDownEvents( ctrl );
				}
			}
		}

		//private void tabControlReports_SelectionChanged(object sender, EventArgs e)
		//{
		//	if ( !ignoreTabSelection )
		//	{
		//		if ( history.Count == 0 || historyIndex >= history.Count )
		//		{
		//			Debug.WriteLine( "History count was invalid!" );
		//			return; // shouldn't happen
		//		}
		//		else if ( historyIndex == history.Count - 1 ) // we're at the tail of the history
		//		{
		//			if ( history.Count == historyCapacity ) // make room for one more
		//			{
		//				history.RemoveAt( 0 );
		//			}
		//		}
		//		else // we've gone back a few entries
		//		{
		//			history.RemoveRange( historyIndex + 1, history.Count - historyIndex - 1 );
		//		}
		//		historyIndex = history.Add( tabControlReports.SelectedIndex );
		//		//Debug.WriteLine("*** History Index: " + historyIndex + ", History Count: " + history.Count);
		//	}
		//	UpdateNavigationEnabledStates();
		//}

		private void menuItemView_NavBack_Click(object sender, EventArgs e)
		{
			NavigateBackward();
		}

		private void menuItemView_NavForward_Click(object sender, EventArgs e)
		{
			NavigateForward();
		}

		//private void UpdateNavigationEnabledStates()
		//{
		//	menuItemView_NavBack.Enabled = historyIndex > 0;
		//	menuItemView_NavForward.Enabled = historyIndex < history.Count - 1;
		//}

		#endregion
	}
}